From 214fc1565aae88c6ce6af436bdf3aa1e59823120 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Fri, 20 Dec 2024 03:04:07 -0700 Subject: [PATCH 01/15] finished bottom draw and fixes to H75 Continued work needed to check other keys like s22. --- key_copier.c | 1481 +++++++++++++++++++++++++++---------------------- key_formats.c | 267 +++++++-- key_formats.h | 62 +-- 3 files changed, 1057 insertions(+), 753 deletions(-) diff --git a/key_copier.c b/key_copier.c index 7ad4660..9a357b3 100644 --- a/key_copier.c +++ b/key_copier.c @@ -1,678 +1,803 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "key_copier_icons.h" -#include "key_formats.h" -#include "key_copier.h" -#define TAG "KeyCopier" - -#define BACKLIGHT_ON 1 - -typedef enum { - KeyCopierSubmenuIndexMeasure, - KeyCopierSubmenuIndexConfigure, - KeyCopierSubmenuIndexSave, - KeyCopierSubmenuIndexLoad, - KeyCopierSubmenuIndexAbout, -} KeyCopierSubmenuIndex; - -typedef enum { - KeyCopierViewSubmenu, - KeyCopierViewTextInput, - KeyCopierViewConfigure_i, - KeyCopierViewConfigure_e, - KeyCopierViewSave, - KeyCopierViewLoad, - KeyCopierViewMeasure, - KeyCopierViewAbout, -} KeyCopierView; - -typedef struct { - ViewDispatcher* view_dispatcher; - NotificationApp* notifications; - Submenu* submenu; - TextInput* text_input; - VariableItemList* variable_item_list_config; - View* view_measure; - View* view_config_e; - View* view_save; - View* view_load; - Widget* widget_about; - VariableItem* key_name_item; - VariableItem* format_item; - char* temp_buffer; - uint32_t temp_buffer_size; - - DialogsApp* dialogs; - FuriString* file_path; -} KeyCopierApp; - -typedef struct { - uint32_t format_index; - FuriString* key_name_str; - uint8_t pin_slc; // The pin that is being adjusted - uint8_t* depth; // The cutting depth - bool data_loaded; - KeyFormat format; -} KeyCopierModel; - -void initialize_model(KeyCopierModel* model) { - if(model->depth != NULL) { - free(model->depth); - } - model->format_index = 0; - memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); - model->depth = (uint8_t*)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); - for(uint8_t i = 0; i <= model->format.pin_num; i++) { - model->depth[i] = model->format.min_depth_ind; - } - model->pin_slc = 1; - model->data_loaded = 0; - model->key_name_str = furi_string_alloc(); -} - -static uint32_t key_copier_navigation_exit_callback(void* _context) { - UNUSED(_context); - return VIEW_NONE; -} - -static uint32_t key_copier_navigation_submenu_callback(void* _context) { - UNUSED(_context); - return KeyCopierViewSubmenu; -} - -static void key_copier_submenu_callback(void* context, uint32_t index) { - KeyCopierApp* app = (KeyCopierApp*)context; - switch(index) { - case KeyCopierSubmenuIndexMeasure: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewMeasure); - break; - case KeyCopierSubmenuIndexConfigure: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure_e); - break; - case KeyCopierSubmenuIndexSave: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSave); - break; - case KeyCopierSubmenuIndexLoad: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewLoad); - break; - case KeyCopierSubmenuIndexAbout: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewAbout); - break; - default: - break; - } -} - -char* manufacturers[COUNT_OF(all_formats)]; -void initialize_manufacturers(char** manufacturers) { - // Populate the manufacturers array - for(size_t i = 0; i < COUNT_OF(all_formats); i++) { - manufacturers[i] = all_formats[i].manufacturer; - } -} - -static void key_copier_format_change(VariableItem* item) { - KeyCopierApp* app = variable_item_get_context(item); - KeyCopierModel* model = view_get_model(app->view_measure); - if(model->data_loaded) { - variable_item_set_current_value_index(item, model->format_index); - } - uint8_t format_index = variable_item_get_current_value_index(item); - if(format_index != model->format_index) { - model->format_index = format_index; - model->format = all_formats[format_index]; - if(model->depth != NULL) { - free(model->depth); - } - model->depth = (uint8_t*)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); - for(uint8_t i = 0; i <= model->format.pin_num; i++) { - model->depth[i] = model->format.min_depth_ind; - } - model->pin_slc = 1; - } - model->data_loaded = false; - variable_item_set_current_value_text(item, model->format.format_name); - model->format = all_formats[model->format_index]; -} -static const char* format_config_label = "Key Format"; -static void key_copier_config_enter_callback(void* context) { - KeyCopierApp* app = (KeyCopierApp*)context; - KeyCopierModel* my_model = view_get_model(app->view_measure); - variable_item_list_reset(app->variable_item_list_config); - // Recreate this view every time we enter it so that it's always updated - app->format_item = variable_item_list_add( - app->variable_item_list_config, - format_config_label, - COUNT_OF(all_formats), - key_copier_format_change, - app); - - View* view_config_i = variable_item_list_get_view(app->variable_item_list_config); - variable_item_set_current_value_index(app->format_item, my_model->format_index); - key_copier_format_change(app->format_item); - view_set_previous_callback(view_config_i, key_copier_navigation_submenu_callback); - view_dispatcher_remove_view( - app->view_dispatcher, KeyCopierViewConfigure_i); // delete the last one - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, view_config_i); - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure_i); // recreate it -} - -static const char* key_name_entry_text = "Enter name"; -static void key_copier_file_saver(void* context) { - KeyCopierApp* app = (KeyCopierApp*)context; - KeyCopierModel* model = view_get_model(app->view_measure); - bool redraw = true; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { furi_string_set(model->key_name_str, app->temp_buffer); }, - redraw); - FuriString* file_path = furi_string_alloc(); - furi_string_printf( - file_path, - "%s/%s%s", - STORAGE_APP_DATA_PATH_PREFIX, - furi_string_get_cstr(model->key_name_str), - KEY_COPIER_FILE_EXTENSION); - - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); - FURI_LOG_D(TAG, "mkdir finished"); - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - do { - const uint32_t version = 1; - const uint32_t pin_num_buffer = (uint32_t)model->format.pin_num; - const uint32_t macs_buffer = (uint32_t)model->format.macs; - FuriString* buffer = furi_string_alloc(); - if(!flipper_format_file_open_always(flipper_format, furi_string_get_cstr(file_path))) - break; - if(!flipper_format_write_header_cstr(flipper_format, "Flipper Key Copier File", version)) - break; - if(!flipper_format_write_string_cstr( - flipper_format, "Manufacturer", model->format.manufacturer)) - break; - if(!flipper_format_write_string_cstr( - flipper_format, "Format Name", model->format.format_name)) - break; - if(!flipper_format_write_string_cstr( - flipper_format, "Data Sheet", model->format.format_link)) - break; - if(!flipper_format_write_uint32(flipper_format, "Number of Pins", &pin_num_buffer, 1)) - break; - if(!flipper_format_write_uint32( - flipper_format, "Maximum Adjacent Cut Specification (MACS)", &macs_buffer, 1)) - break; - for(int i = 0; i < model->format.pin_num; i++) { - if(i < model->format.pin_num - 1) { - furi_string_cat_printf(buffer, "%d-", model->depth[i]); - } else { - furi_string_cat_printf(buffer, "%d", model->depth[i]); - } - } - if(!flipper_format_write_string(flipper_format, "Bitting Pattern", buffer)) break; - furi_string_free(buffer); - // signal that the file was written successfully - } while(0); - flipper_format_free(flipper_format); - - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); -} - -static void key_copier_view_save_callback(void* context) { - KeyCopierApp* app = (KeyCopierApp*)context; - // Header to display on the text input screen. - text_input_set_header_text(app->text_input, key_name_entry_text); - - // Copy the current name into the temporary buffer. - bool redraw = false; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - strncpy( - app->temp_buffer, - furi_string_get_cstr(model->key_name_str), - app->temp_buffer_size); - }, - redraw); - - // Configure the text input. When user enters text and clicks OK, key_copier_file_saver be called. - bool clear_previous_text = false; - text_input_set_result_callback( - app->text_input, - key_copier_file_saver, - app, - app->temp_buffer, - app->temp_buffer_size, - clear_previous_text); - - view_set_previous_callback( - text_input_get_view(app->text_input), key_copier_navigation_submenu_callback); - - // Show text input dialog. - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); -} - -static void key_copier_view_load_callback(void* context) { - KeyCopierApp* app = (KeyCopierApp*)context; - KeyCopierModel* model = view_get_model(app->view_measure); - DialogsFileBrowserOptions browser_options; - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); - dialog_file_browser_set_basic_options(&browser_options, KEY_COPIER_FILE_EXTENSION, &I_icon); - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - furi_string_set(app->file_path, browser_options.base_path); - if(dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) { - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - do { - if(!flipper_format_file_open_existing( - flipper_format, furi_string_get_cstr(app->file_path))) - break; - FuriString* format_buffer = furi_string_alloc(); - FuriString* depth_buffer = furi_string_alloc(); - if(!flipper_format_read_string(flipper_format, "Format Name", format_buffer)) break; - if(!flipper_format_read_string(flipper_format, "Bitting Pattern", depth_buffer)) break; - for(size_t i = 0; i < COUNT_OF(all_formats); i++) { - if(!strcmp(furi_string_get_cstr(format_buffer), all_formats[i].format_name)) { - model->format_index = (uint32_t)i; - model->format = all_formats[model->format_index]; - } - } - - for(int i = 0; i < model->format.pin_num; i++) { - model->depth[i] = (uint8_t)(furi_string_get_char(depth_buffer, i * 2) - '0'); - } - model->data_loaded = true; - // signal that the file was read successfully - } while(0); - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - } - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); -} - -static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { - static double inches_per_px = (double)INCHES_PER_PX; - canvas_set_bitmap_mode(canvas, true); - KeyCopierModel* my_model = (KeyCopierModel*)model; - KeyFormat my_format = my_model->format; - FuriString* buffer = furi_string_alloc(); - int pin_half_width_px = (int)round((my_format.pin_width_inch / inches_per_px) / 2); - int pin_step_px = (int)round(my_format.pin_increment_inch / inches_per_px); - double drill_radians = - (180 - my_format.drill_angle) / 2 / 180 * (double)M_PI; // Convert angle to radians - double tangent = tan(drill_radians); - int top_contour_px = (int)round(63 - my_format.uncut_depth_inch / inches_per_px); - int post_extra_x_px = 0; - int pre_extra_x_px = 0; - for(int current_pin = 1; current_pin <= my_model->format.pin_num; current_pin += 1) { - double current_center_px = - my_format.first_pin_inch + (current_pin - 1) * my_format.pin_increment_inch; - int pin_center_px = (int)round(current_center_px / inches_per_px); - - furi_string_printf(buffer, "%d", my_model->depth[current_pin - 1]); - canvas_draw_str_aligned( - canvas, - pin_center_px, - top_contour_px - 12, - AlignCenter, - AlignCenter, - furi_string_get_cstr(buffer)); - - canvas_draw_line( - canvas, - pin_center_px, - top_contour_px - 5, - pin_center_px, - top_contour_px); // the vertical line to indicate pin center - int current_depth = my_model->depth[current_pin - 1] - my_format.min_depth_ind; - int current_depth_px = - (int)round(current_depth * my_format.depth_step_inch / inches_per_px); - canvas_draw_line( - canvas, - pin_center_px - pin_half_width_px, - top_contour_px + current_depth_px, - pin_center_px + pin_half_width_px, - top_contour_px + current_depth_px); // draw pin width horizontal line - int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; - int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; - if(current_pin == 1) { - canvas_draw_line( - canvas, - 0, - top_contour_px, - pin_center_px - pin_half_width_px - current_depth_px, - top_contour_px); - last_depth = 0; - pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); - } - if(current_pin == my_model->format.pin_num) { - next_depth = 0; - } - if((last_depth + current_depth) > my_format.clearance) { //yes intersection - - if(current_pin != 1) { - pre_extra_x_px = - min(max(pin_step_px - post_extra_x_px, pin_half_width_px), - pin_step_px - pin_half_width_px); - } - canvas_draw_line( - canvas, - pin_center_px - pre_extra_x_px, - top_contour_px + - max((int)round( - (current_depth_px - (pre_extra_x_px - pin_half_width_px)) * tangent), - 0), - pin_center_px - pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent)); - } else { - int last_depth_px = (int)round(last_depth * my_format.depth_step_inch / inches_per_px); - int down_slope_start_x_px = pin_center_px - pin_half_width_px - current_depth_px; - canvas_draw_line( - canvas, - pin_center_px - pin_half_width_px - current_depth_px, - top_contour_px, - pin_center_px - pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent)); - canvas_draw_line( - canvas, - min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, - down_slope_start_x_px), - top_contour_px, - down_slope_start_x_px, - top_contour_px); - } - if((current_depth + next_depth) > my_format.clearance) { //yes intersection - double numerator = (double)current_depth; - double denominator = (double)(current_depth + next_depth); - double product = (numerator / denominator) * pin_step_px; - post_extra_x_px = - (int)min(max(product, pin_half_width_px), pin_step_px - pin_half_width_px); - canvas_draw_line( - canvas, - pin_center_px + pin_half_width_px, - top_contour_px + current_depth_px, - pin_center_px + post_extra_x_px, - top_contour_px + - max(current_depth_px - - (int)round((post_extra_x_px - pin_half_width_px) * tangent), - 0)); - } else { // no intersection - canvas_draw_line( - canvas, - pin_center_px + pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent), - pin_center_px + pin_half_width_px + current_depth_px, - top_contour_px); - } - } - - int level_contour_px = - (int)round((my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); - int elbow_px = (int)round(my_format.elbow_inch / inches_per_px); - canvas_draw_line(canvas, 0, 62, level_contour_px, 62); - canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, 62 - elbow_px); - - int slc_pin_px = (int)round( - (my_format.first_pin_inch + (my_model->pin_slc - 1) * my_format.pin_increment_inch) / - inches_per_px); - canvas_draw_icon(canvas, slc_pin_px - 2, top_contour_px - 25, &I_arrow_down); - - furi_string_printf(buffer, "%s", my_format.format_name); - canvas_draw_str(canvas, 110, 10, furi_string_get_cstr(buffer)); - furi_string_free(buffer); -} - -static bool key_copier_view_measure_input_callback(InputEvent* event, void* context) { - KeyCopierApp* app = (KeyCopierApp*)context; - if(event->type == InputTypeShort) { - switch(event->key) { - case InputKeyLeft: { - bool redraw = true; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - if(model->pin_slc > 1) { - model->pin_slc--; - } - }, - redraw); - break; - } - case InputKeyRight: { - bool redraw = true; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - if(model->pin_slc < model->format.pin_num) { - model->pin_slc++; - } - }, - redraw); - break; - } - case InputKeyUp: { - bool redraw = true; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - if(model->depth[model->pin_slc - 1] > model->format.min_depth_ind) { - if(model->pin_slc == 1) { //first pin only limited by the next one - if(model->depth[model->pin_slc] - model->depth[model->pin_slc - 1] < - model->format.macs) - model->depth[model->pin_slc - 1]--; - } else if( - model->pin_slc == - model->format.pin_num) { //last pin only limited by the previous one - if(model->depth[model->pin_slc - 2] - - model->depth[model->pin_slc - 1] < - model->format.macs) { - model->depth[model->pin_slc - 1]--; - } - } else { - if(model->depth[model->pin_slc] - model->depth[model->pin_slc - 1] < - model->format.macs && - model->depth[model->pin_slc - 2] - - model->depth[model->pin_slc - 1] < - model->format.macs) { - model->depth[model->pin_slc - 1]--; - } - } - } - }, - redraw); - break; - } - case InputKeyDown: { - bool redraw = true; - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - if(model->depth[model->pin_slc - 1] < model->format.max_depth_ind) { - if(model->pin_slc == 1) { //first pin only limited by the next one - if(model->depth[model->pin_slc - 1] - model->depth[model->pin_slc] < - model->format.macs) - model->depth[model->pin_slc - 1]++; - } else if( - model->pin_slc == - model->format.pin_num) { //last pin only limited by the previous one - if(model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc - 2] < - model->format.macs) { - model->depth[model->pin_slc - 1]++; - } - } else { - if(model->depth[model->pin_slc - 1] - model->depth[model->pin_slc] < - model->format.macs && - model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc - 2] < - model->format.macs) { - model->depth[model->pin_slc - 1]++; - } - } - } - }, - redraw); - break; - } - default: - // Handle other keys or do nothing - break; - } - } - - return false; -} - -static KeyCopierApp* key_copier_app_alloc() { - KeyCopierApp* app = (KeyCopierApp*)malloc(sizeof(KeyCopierApp)); - - Gui* gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - app->dialogs = furi_record_open(RECORD_DIALOGS); - app->file_path = furi_string_alloc(); - app->submenu = submenu_alloc(); - submenu_add_item( - app->submenu, "Measure", KeyCopierSubmenuIndexMeasure, key_copier_submenu_callback, app); - submenu_add_item( - app->submenu, "Config", KeyCopierSubmenuIndexConfigure, key_copier_submenu_callback, app); - submenu_add_item( - app->submenu, "Save", KeyCopierSubmenuIndexSave, key_copier_submenu_callback, app); - submenu_add_item( - app->submenu, "Load", KeyCopierSubmenuIndexLoad, key_copier_submenu_callback, app); - submenu_add_item( - app->submenu, "About", KeyCopierSubmenuIndexAbout, key_copier_submenu_callback, app); - view_set_previous_callback( - submenu_get_view(app->submenu), key_copier_navigation_exit_callback); - view_dispatcher_add_view( - app->view_dispatcher, KeyCopierViewSubmenu, submenu_get_view(app->submenu)); - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); - - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, KeyCopierViewTextInput, text_input_get_view(app->text_input)); - app->temp_buffer_size = 32; - app->temp_buffer = (char*)malloc(app->temp_buffer_size); - app->temp_buffer = ""; - - app->view_measure = view_alloc(); - view_set_draw_callback(app->view_measure, key_copier_view_measure_draw_callback); - view_set_input_callback(app->view_measure, key_copier_view_measure_input_callback); - view_set_previous_callback(app->view_measure, key_copier_navigation_submenu_callback); - view_set_context(app->view_measure, app); - view_allocate_model(app->view_measure, ViewModelTypeLockFree, sizeof(KeyCopierModel)); - KeyCopierModel* model = view_get_model(app->view_measure); - - initialize_model(model); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewMeasure, app->view_measure); - - app->variable_item_list_config = variable_item_list_alloc(); - app->view_config_e = view_alloc(); - view_set_context(app->view_config_e, app); - view_set_previous_callback(app->view_config_e, key_copier_navigation_submenu_callback); - view_set_enter_callback(app->view_config_e, key_copier_config_enter_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_e, app->view_config_e); - - View* view_buffer = view_alloc(); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, view_buffer); - - app->view_save = view_alloc(); - view_set_context(app->view_save, app); - view_set_enter_callback(app->view_save, key_copier_view_save_callback); - view_set_previous_callback(app->view_save, key_copier_navigation_submenu_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSave, app->view_save); - - app->view_load = view_alloc(); - view_set_context(app->view_load, app); - view_set_enter_callback(app->view_load, key_copier_view_load_callback); - view_set_previous_callback(app->view_load, key_copier_navigation_submenu_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewLoad, app->view_load); - - app->widget_about = widget_alloc(); - widget_add_text_scroll_element( - app->widget_about, - 0, - 0, - 128, - 64, - "Key Maker App 1.0\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place it on top of the screen.\n\n2. Use the contour to align your key.\n\n3. Adjust each pin's depth until they match. It's easier if you look with one eye closed.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial thanks to Derek Jamison's Skeleton App Template."); - view_set_previous_callback( - widget_get_view(app->widget_about), key_copier_navigation_submenu_callback); - view_dispatcher_add_view( - app->view_dispatcher, KeyCopierViewAbout, widget_get_view(app->widget_about)); - - app->notifications = furi_record_open(RECORD_NOTIFICATION); - -#ifdef BACKLIGHT_ON - notification_message(app->notifications, &sequence_display_backlight_enforce_on); -#endif - - return app; -} - -static void key_copier_app_free(KeyCopierApp* app) { -#ifdef BACKLIGHT_ON - notification_message(app->notifications, &sequence_display_backlight_enforce_auto); -#endif - furi_record_close(RECORD_NOTIFICATION); - - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewTextInput); - text_input_free(app->text_input); - free(app->temp_buffer); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewAbout); - widget_free(app->widget_about); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewMeasure); - with_view_model( - app->view_measure, - KeyCopierModel * model, - { - if(model->depth != NULL) { - free(model->depth); - } - }, - false); - view_free(app->view_measure); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_e); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_i); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSave); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewLoad); - variable_item_list_free(app->variable_item_list_config); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSubmenu); - submenu_free(app->submenu); - view_dispatcher_free(app->view_dispatcher); - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t main_key_copier_app(void* _p) { - UNUSED(_p); - - KeyCopierApp* app = key_copier_app_alloc(); - view_dispatcher_run(app->view_dispatcher); - - key_copier_app_free(app); - return 0; -} +#include "key_copier.h" +#include "key_copier_icons.h" +#include "key_formats.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "KeyCopier" + +#define BACKLIGHT_ON 1 + +typedef enum { + KeyCopierSubmenuIndexMeasure, + KeyCopierSubmenuIndexConfigure, + KeyCopierSubmenuIndexSave, + KeyCopierSubmenuIndexLoad, + KeyCopierSubmenuIndexAbout, +} KeyCopierSubmenuIndex; + +typedef enum { + KeyCopierViewSubmenu, + KeyCopierViewTextInput, + KeyCopierViewConfigure_i, + KeyCopierViewConfigure_e, + KeyCopierViewSave, + KeyCopierViewLoad, + KeyCopierViewMeasure, + KeyCopierViewAbout, +} KeyCopierView; + +typedef struct { + ViewDispatcher *view_dispatcher; + NotificationApp *notifications; + Submenu *submenu; + TextInput *text_input; + VariableItemList *variable_item_list_config; + View *view_measure; + View *view_config_e; + View *view_save; + View *view_load; + Widget *widget_about; + VariableItem *key_name_item; + VariableItem *format_item; + char *temp_buffer; + uint32_t temp_buffer_size; + + DialogsApp *dialogs; + FuriString *file_path; +} KeyCopierApp; + +typedef struct { + uint32_t format_index; + FuriString *key_name_str; + uint8_t pin_slc; // The pin that is being adjusted + uint8_t *depth; // The cutting depth + bool data_loaded; + KeyFormat format; +} KeyCopierModel; + +void initialize_model(KeyCopierModel *model) { + if (model->depth != NULL) { + free(model->depth); + } + model->format_index = 0; + memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); + model->depth = + (uint8_t *)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); + for (uint8_t i = 0; i <= model->format.pin_num; i++) { + model->depth[i] = model->format.min_depth_ind; + } + model->pin_slc = 1; + model->data_loaded = 0; + model->key_name_str = furi_string_alloc(); +} + +static uint32_t key_copier_navigation_exit_callback(void *_context) { + UNUSED(_context); + return VIEW_NONE; +} + +static uint32_t key_copier_navigation_submenu_callback(void *_context) { + UNUSED(_context); + return KeyCopierViewSubmenu; +} + +static void key_copier_submenu_callback(void *context, uint32_t index) { + KeyCopierApp *app = (KeyCopierApp *)context; + switch (index) { + case KeyCopierSubmenuIndexMeasure: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewMeasure); + break; + case KeyCopierSubmenuIndexConfigure: + view_dispatcher_switch_to_view(app->view_dispatcher, + KeyCopierViewConfigure_e); + break; + case KeyCopierSubmenuIndexSave: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSave); + break; + case KeyCopierSubmenuIndexLoad: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewLoad); + break; + case KeyCopierSubmenuIndexAbout: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewAbout); + break; + default: + break; + } +} + +char *manufacturers[COUNT_OF(all_formats)]; +void initialize_manufacturers(char **manufacturers) { + // Populate the manufacturers array + for (size_t i = 0; i < COUNT_OF(all_formats); i++) { + manufacturers[i] = all_formats[i].manufacturer; + } +} + +static void key_copier_format_change(VariableItem *item) { + KeyCopierApp *app = variable_item_get_context(item); + KeyCopierModel *model = view_get_model(app->view_measure); + if (model->data_loaded) { + variable_item_set_current_value_index(item, model->format_index); + } + uint8_t format_index = variable_item_get_current_value_index(item); + if (format_index != model->format_index) { + model->format_index = format_index; + model->format = all_formats[format_index]; + if (model->depth != NULL) { + free(model->depth); + } + model->depth = + (uint8_t *)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); + for (uint8_t i = 0; i <= model->format.pin_num; i++) { + model->depth[i] = model->format.min_depth_ind; + } + model->pin_slc = 1; + } + model->data_loaded = false; + variable_item_set_current_value_text(item, model->format.format_name); + model->format = all_formats[model->format_index]; +} +static const char *format_config_label = "Key Format"; +static void key_copier_config_enter_callback(void *context) { + KeyCopierApp *app = (KeyCopierApp *)context; + KeyCopierModel *my_model = view_get_model(app->view_measure); + variable_item_list_reset(app->variable_item_list_config); + // Recreate this view every time we enter it so that it's always updated + app->format_item = variable_item_list_add( + app->variable_item_list_config, format_config_label, + COUNT_OF(all_formats), key_copier_format_change, app); + + View *view_config_i = + variable_item_list_get_view(app->variable_item_list_config); + variable_item_set_current_value_index(app->format_item, + my_model->format_index); + key_copier_format_change(app->format_item); + view_set_previous_callback(view_config_i, + key_copier_navigation_submenu_callback); + view_dispatcher_remove_view(app->view_dispatcher, + KeyCopierViewConfigure_i); // delete the last one + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, + view_config_i); + view_dispatcher_switch_to_view(app->view_dispatcher, + KeyCopierViewConfigure_i); // recreate it +} + +static const char *key_name_entry_text = "Enter name"; +static void key_copier_file_saver(void *context) { + KeyCopierApp *app = (KeyCopierApp *)context; + KeyCopierModel *model = view_get_model(app->view_measure); + bool redraw = true; + with_view_model( + app->view_measure, KeyCopierModel * model, + { furi_string_set(model->key_name_str, app->temp_buffer); }, redraw); + FuriString *file_path = furi_string_alloc(); + furi_string_printf(file_path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, + furi_string_get_cstr(model->key_name_str), + KEY_COPIER_FILE_EXTENSION); + + Storage *storage = furi_record_open(RECORD_STORAGE); + storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); + FURI_LOG_D(TAG, "mkdir finished"); + FlipperFormat *flipper_format = flipper_format_file_alloc(storage); + do { + const uint32_t version = 1; + const uint32_t pin_num_buffer = (uint32_t)model->format.pin_num; + const uint32_t macs_buffer = (uint32_t)model->format.macs; + FuriString *buffer = furi_string_alloc(); + if (!flipper_format_file_open_always(flipper_format, + furi_string_get_cstr(file_path))) + break; + if (!flipper_format_write_header_cstr(flipper_format, + "Flipper Key Copier File", version)) + break; + if (!flipper_format_write_string_cstr(flipper_format, "Manufacturer", + model->format.manufacturer)) + break; + if (!flipper_format_write_string_cstr(flipper_format, "Format Name", + model->format.format_name)) + break; + if (!flipper_format_write_string_cstr(flipper_format, "Data Sheet", + model->format.format_link)) + break; + if (!flipper_format_write_uint32(flipper_format, "Number of Pins", + &pin_num_buffer, 1)) + break; + if (!flipper_format_write_uint32( + flipper_format, "Maximum Adjacent Cut Specification (MACS)", + &macs_buffer, 1)) + break; + for (int i = 0; i < model->format.pin_num; i++) { + if (i < model->format.pin_num - 1) { + furi_string_cat_printf(buffer, "%d-", model->depth[i]); + } else { + furi_string_cat_printf(buffer, "%d", model->depth[i]); + } + } + if (!flipper_format_write_string(flipper_format, "Bitting Pattern", buffer)) + break; + furi_string_free(buffer); + // signal that the file was written successfully + } while (0); + flipper_format_free(flipper_format); + + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); +} + +static void key_copier_view_save_callback(void *context) { + KeyCopierApp *app = (KeyCopierApp *)context; + // Header to display on the text input screen. + text_input_set_header_text(app->text_input, key_name_entry_text); + + // Copy the current name into the temporary buffer. + bool redraw = false; + with_view_model( + app->view_measure, KeyCopierModel * model, + { + strncpy(app->temp_buffer, furi_string_get_cstr(model->key_name_str), + app->temp_buffer_size); + }, + redraw); + + // Configure the text input. When user enters text and clicks OK, + // key_copier_file_saver be called. + bool clear_previous_text = false; + text_input_set_result_callback(app->text_input, key_copier_file_saver, app, + app->temp_buffer, app->temp_buffer_size, + clear_previous_text); + + view_set_previous_callback(text_input_get_view(app->text_input), + key_copier_navigation_submenu_callback); + + // Show text input dialog. + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); +} + +static void key_copier_view_load_callback(void *context) { + KeyCopierApp *app = (KeyCopierApp *)context; + KeyCopierModel *model = view_get_model(app->view_measure); + DialogsFileBrowserOptions browser_options; + Storage *storage = furi_record_open(RECORD_STORAGE); + storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); + dialog_file_browser_set_basic_options(&browser_options, + KEY_COPIER_FILE_EXTENSION, &I_icon); + browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; + furi_string_set(app->file_path, browser_options.base_path); + if (dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, + &browser_options)) { + FlipperFormat *flipper_format = flipper_format_file_alloc(storage); + do { + if (!flipper_format_file_open_existing( + flipper_format, furi_string_get_cstr(app->file_path))) + break; + FuriString *format_buffer = furi_string_alloc(); + FuriString *depth_buffer = furi_string_alloc(); + if (!flipper_format_read_string(flipper_format, "Format Name", + format_buffer)) + break; + if (!flipper_format_read_string(flipper_format, "Bitting Pattern", + depth_buffer)) + break; + for (size_t i = 0; i < COUNT_OF(all_formats); i++) { + if (!strcmp(furi_string_get_cstr(format_buffer), + all_formats[i].format_name)) { + model->format_index = (uint32_t)i; + model->format = all_formats[model->format_index]; + } + } + + for (int i = 0; i < model->format.pin_num; i++) { + model->depth[i] = + (uint8_t)(furi_string_get_char(depth_buffer, i * 2) - '0'); + } + model->data_loaded = true; + // signal that the file was read successfully + } while (0); + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + } + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); +} + +static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { + static double inches_per_px = (double)INCHES_PER_PX; + canvas_set_bitmap_mode(canvas, true); + KeyCopierModel *my_model = (KeyCopierModel *)model; + KeyFormat my_format = my_model->format; + FuriString *buffer = furi_string_alloc(); + int pin_half_width_px = + (int)round((my_format.pin_width_inch / inches_per_px) / 2); + int pin_step_px = (int)round(my_format.pin_increment_inch / inches_per_px); + double drill_radians = (180 - my_format.drill_angle) / 2 / 180 * + (double)M_PI; // Convert angle to radians + double tangent = tan(drill_radians); + int top_contour_px = + (int)round(62 - my_format.uncut_depth_inch / inches_per_px); + int bottom_contour_px = 0; + // int bottom_contour_px = + // top_contour_px + (int)round(my_format.uncut_depth_inch / + // inches_per_px); + if (my_format.sides == 2) + bottom_contour_px = + top_contour_px + (int)round(my_format.uncut_depth_inch / inches_per_px); + int post_extra_x_px = 0; + int pre_extra_x_px = 0; + int bottom_post_extra_x_px = 0; // new + int bottom_pre_extra_x_px = 0; // new + for (int current_pin = 1; current_pin <= my_model->format.pin_num; + current_pin += 1) { + double current_center_px = my_format.first_pin_inch + + (current_pin - 1) * my_format.pin_increment_inch; + int pin_center_px = (int)round(current_center_px / inches_per_px); + + furi_string_printf(buffer, "%d", my_model->depth[current_pin - 1]); + canvas_draw_str_aligned(canvas, pin_center_px, top_contour_px - 12, + AlignCenter, AlignCenter, + furi_string_get_cstr(buffer)); + + canvas_draw_line( + canvas, pin_center_px, top_contour_px - 5, pin_center_px, + top_contour_px); // the vertical line to indicate pin center + int current_depth = + my_model->depth[current_pin - 1] - my_format.min_depth_ind; + int current_depth_px = + (int)round(current_depth * my_format.depth_step_inch / inches_per_px); + canvas_draw_line( + canvas, pin_center_px - pin_half_width_px, + top_contour_px + current_depth_px, pin_center_px + pin_half_width_px, + top_contour_px + + current_depth_px); // draw top pin width horizontal line + + // if(my_format.sides == 2) //old (remove new start to end and remove // for + // this line to fix) + + if (my_format.sides == 2) { // new start + int last_depth = + my_model->depth[current_pin - 2] - my_format.min_depth_ind; + int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; + int current_depth = + my_model->depth[current_pin - 1] - my_format.min_depth_ind; + int current_depth_px = + (int)round(current_depth * my_format.depth_step_inch / inches_per_px); + + // Draw horizontal line for bottom pin + canvas_draw_line(canvas, pin_center_px - pin_half_width_px, + bottom_contour_px - current_depth_px, + pin_center_px + pin_half_width_px, + bottom_contour_px - current_depth_px); + + // Handle first pin for bottom + if (current_pin == 1) { + canvas_draw_line(canvas, 0, bottom_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px); + last_depth = 0; + bottom_pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); + } + + // Handle left side intersection for bottom + if ((last_depth + current_depth) > my_format.clearance) { + if (current_pin != 1) { + bottom_pre_extra_x_px = + min(max(pin_step_px - bottom_post_extra_x_px, pin_half_width_px), + pin_step_px - pin_half_width_px); + } + canvas_draw_line( + canvas, pin_center_px - bottom_pre_extra_x_px, + bottom_contour_px - + max((int)round((current_depth_px - + (bottom_pre_extra_x_px - pin_half_width_px)) * + tangent), + 0), + pin_center_px - pin_half_width_px, + bottom_contour_px - (int)round(current_depth_px * tangent)); + } else { + int last_depth_px = + (int)round(last_depth * my_format.depth_step_inch / inches_per_px); + int up_slope_start_x_px = + pin_center_px - pin_half_width_px - current_depth_px; + canvas_draw_line( + canvas, pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px, pin_center_px - pin_half_width_px, + bottom_contour_px - (int)round(current_depth_px * tangent)); + canvas_draw_line( + canvas, + min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, + up_slope_start_x_px), + bottom_contour_px, up_slope_start_x_px, bottom_contour_px); + } + + // Handle right side intersection for bottom + if ((current_depth + next_depth) > my_format.clearance) { + double numerator = (double)current_depth; + double denominator = (double)(current_depth + next_depth); + double product = (numerator / denominator) * pin_step_px; + bottom_post_extra_x_px = (int)min(max(product, pin_half_width_px), + pin_step_px - pin_half_width_px); + canvas_draw_line( + canvas, pin_center_px + pin_half_width_px, + bottom_contour_px - current_depth_px, + pin_center_px + bottom_post_extra_x_px, + bottom_contour_px - + max(current_depth_px - (int)round((bottom_post_extra_x_px - + pin_half_width_px) * + tangent), + 0)); + } else { + canvas_draw_line(canvas, pin_center_px + pin_half_width_px, + bottom_contour_px - + (int)round(current_depth_px * tangent), + pin_center_px + pin_half_width_px + current_depth_px, + bottom_contour_px); + } + } + // new end + + canvas_draw_line( + canvas, pin_center_px - pin_half_width_px, + bottom_contour_px - current_depth_px, pin_center_px + pin_half_width_px, + bottom_contour_px - + current_depth_px); // draw bottom pin width horizontal line + + int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; + int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; + if (current_pin == 1) { + canvas_draw_line(canvas, 0, top_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + top_contour_px); // draw top shoulder + last_depth = 0; + pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); + + canvas_draw_line( + canvas, 0, bottom_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px); // draw bottom shoulder (hidden by level contour) + } + if (current_pin == my_model->format.pin_num) { + next_depth = 0; + } + if ((last_depth + current_depth) > my_format.clearance) { // yes + // intersection + + if (current_pin != 1) { + pre_extra_x_px = + min(max(pin_step_px - post_extra_x_px, pin_half_width_px), + pin_step_px - pin_half_width_px); + } + canvas_draw_line( + canvas, pin_center_px - pre_extra_x_px, + top_contour_px + + max((int)round((current_depth_px - + (pre_extra_x_px - pin_half_width_px)) * + tangent), + 0), + pin_center_px - pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent)); + } else { + int last_depth_px = + (int)round(last_depth * my_format.depth_step_inch / inches_per_px); + int down_slope_start_x_px = + pin_center_px - pin_half_width_px - current_depth_px; + canvas_draw_line(canvas, + pin_center_px - pin_half_width_px - current_depth_px, + top_contour_px, pin_center_px - pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent)); + canvas_draw_line( + canvas, + min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, + down_slope_start_x_px), + top_contour_px, down_slope_start_x_px, top_contour_px); + } + if ((current_depth + next_depth) > my_format.clearance) { // yes + // intersection + double numerator = (double)current_depth; + double denominator = (double)(current_depth + next_depth); + double product = (numerator / denominator) * pin_step_px; + post_extra_x_px = (int)min(max(product, pin_half_width_px), + pin_step_px - pin_half_width_px); + canvas_draw_line( + canvas, pin_center_px + pin_half_width_px, + top_contour_px + current_depth_px, pin_center_px + post_extra_x_px, + top_contour_px + + max(current_depth_px - + (int)round((post_extra_x_px - pin_half_width_px) * + tangent), + 0)); + } else { // no intersection + canvas_draw_line(canvas, pin_center_px + pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent), + pin_center_px + pin_half_width_px + current_depth_px, + top_contour_px); + } + } + + int level_contour_px = (int)round( + (my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); + int elbow_px = (int)round(my_format.elbow_inch / inches_per_px); + canvas_draw_line(canvas, 0, 62, level_contour_px, 62); + canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, + 62 - elbow_px); + canvas_draw_line(canvas, 1, 1, 1, 63); + + int slc_pin_px = + (int)round((my_format.first_pin_inch + + (my_model->pin_slc - 1) * my_format.pin_increment_inch) / + inches_per_px); + canvas_draw_icon(canvas, slc_pin_px - 2, top_contour_px - 25, &I_arrow_down); + + furi_string_printf(buffer, "%s", my_format.format_name); + canvas_draw_str(canvas, 100, 10, furi_string_get_cstr(buffer)); + furi_string_free(buffer); +} + +static bool key_copier_view_measure_input_callback(InputEvent *event, + void *context) { + KeyCopierApp *app = (KeyCopierApp *)context; + if (event->type == InputTypeShort) { + switch (event->key) { + case InputKeyLeft: { + bool redraw = true; + with_view_model( + app->view_measure, KeyCopierModel * model, + { + if (model->pin_slc > 1) { + model->pin_slc--; + } + }, + redraw); + break; + } + case InputKeyRight: { + bool redraw = true; + with_view_model( + app->view_measure, KeyCopierModel * model, + { + if (model->pin_slc < model->format.pin_num) { + model->pin_slc++; + } + }, + redraw); + break; + } + case InputKeyUp: { + bool redraw = true; + with_view_model( + app->view_measure, KeyCopierModel * model, + { + if (model->depth[model->pin_slc - 1] > + model->format.min_depth_ind) { + if (model->pin_slc == + 1) { // first pin only limited by the next one + if (model->depth[model->pin_slc] - + model->depth[model->pin_slc - 1] < + model->format.macs) + model->depth[model->pin_slc - 1]--; + } else if (model->pin_slc == + model->format.pin_num) { // last pin only limited by + // the previous one + if (model->depth[model->pin_slc - 2] - + model->depth[model->pin_slc - 1] < + model->format.macs) { + model->depth[model->pin_slc - 1]--; + } + } else { + if (model->depth[model->pin_slc] - + model->depth[model->pin_slc - 1] < + model->format.macs && + model->depth[model->pin_slc - 2] - + model->depth[model->pin_slc - 1] < + model->format.macs) { + model->depth[model->pin_slc - 1]--; + } + } + } + }, + redraw); + break; + } + case InputKeyDown: { + bool redraw = true; + with_view_model( + app->view_measure, KeyCopierModel * model, + { + if (model->depth[model->pin_slc - 1] < + model->format.max_depth_ind) { + if (model->pin_slc == + 1) { // first pin only limited by the next one + if (model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc] < + model->format.macs) + model->depth[model->pin_slc - 1]++; + } else if (model->pin_slc == + model->format.pin_num) { // last pin only limited by + // the previous one + if (model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc - 2] < + model->format.macs) { + model->depth[model->pin_slc - 1]++; + } + } else { + if (model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc] < + model->format.macs && + model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc - 2] < + model->format.macs) { + model->depth[model->pin_slc - 1]++; + } + } + } + }, + redraw); + break; + } + default: + // Handle other keys or do nothing + break; + } + } + + return false; +} + +static KeyCopierApp *key_copier_app_alloc() { + KeyCopierApp *app = (KeyCopierApp *)malloc(sizeof(KeyCopierApp)); + + Gui *gui = furi_record_open(RECORD_GUI); + + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_attach_to_gui(app->view_dispatcher, gui, + ViewDispatcherTypeFullscreen); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + app->dialogs = furi_record_open(RECORD_DIALOGS); + app->file_path = furi_string_alloc(); + app->submenu = submenu_alloc(); + submenu_add_item(app->submenu, "Measure", KeyCopierSubmenuIndexMeasure, + key_copier_submenu_callback, app); + submenu_add_item(app->submenu, "Config", KeyCopierSubmenuIndexConfigure, + key_copier_submenu_callback, app); + submenu_add_item(app->submenu, "Save", KeyCopierSubmenuIndexSave, + key_copier_submenu_callback, app); + submenu_add_item(app->submenu, "Load", KeyCopierSubmenuIndexLoad, + key_copier_submenu_callback, app); + submenu_add_item(app->submenu, "About", KeyCopierSubmenuIndexAbout, + key_copier_submenu_callback, app); + view_set_previous_callback(submenu_get_view(app->submenu), + key_copier_navigation_exit_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSubmenu, + submenu_get_view(app->submenu)); + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); + + app->text_input = text_input_alloc(); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewTextInput, + text_input_get_view(app->text_input)); + app->temp_buffer_size = 32; + app->temp_buffer = (char *)malloc(app->temp_buffer_size); + app->temp_buffer = ""; + + app->view_measure = view_alloc(); + view_set_draw_callback(app->view_measure, + key_copier_view_measure_draw_callback); + view_set_input_callback(app->view_measure, + key_copier_view_measure_input_callback); + view_set_previous_callback(app->view_measure, + key_copier_navigation_submenu_callback); + view_set_context(app->view_measure, app); + view_allocate_model(app->view_measure, ViewModelTypeLockFree, + sizeof(KeyCopierModel)); + KeyCopierModel *model = view_get_model(app->view_measure); + + initialize_model(model); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewMeasure, + app->view_measure); + + app->variable_item_list_config = variable_item_list_alloc(); + app->view_config_e = view_alloc(); + view_set_context(app->view_config_e, app); + view_set_previous_callback(app->view_config_e, + key_copier_navigation_submenu_callback); + view_set_enter_callback(app->view_config_e, key_copier_config_enter_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_e, + app->view_config_e); + + View *view_buffer = view_alloc(); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, + view_buffer); + + app->view_save = view_alloc(); + view_set_context(app->view_save, app); + view_set_enter_callback(app->view_save, key_copier_view_save_callback); + view_set_previous_callback(app->view_save, + key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSave, + app->view_save); + + app->view_load = view_alloc(); + view_set_context(app->view_load, app); + view_set_enter_callback(app->view_load, key_copier_view_load_callback); + view_set_previous_callback(app->view_load, + key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewLoad, + app->view_load); + + app->widget_about = widget_alloc(); + widget_add_text_scroll_element( + app->widget_about, 0, 0, 128, 64, + "Key Maker App 1.0\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place " + "it on top of the screen.\n\n2. Use the contour to align your key.\n\n3. " + "Adjust each pin's depth until they match. It's easier if you look with " + "one eye closed.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial " + "thanks to Derek Jamison's Skeleton App Template."); + view_set_previous_callback(widget_get_view(app->widget_about), + key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewAbout, + widget_get_view(app->widget_about)); + + app->notifications = furi_record_open(RECORD_NOTIFICATION); + +#ifdef BACKLIGHT_ON + notification_message(app->notifications, + &sequence_display_backlight_enforce_on); +#endif + + return app; +} + +static void key_copier_app_free(KeyCopierApp *app) { +#ifdef BACKLIGHT_ON + notification_message(app->notifications, + &sequence_display_backlight_enforce_auto); +#endif + furi_record_close(RECORD_NOTIFICATION); + + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewTextInput); + text_input_free(app->text_input); + free(app->temp_buffer); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewAbout); + widget_free(app->widget_about); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewMeasure); + with_view_model( + app->view_measure, KeyCopierModel * model, + { + if (model->depth != NULL) { + free(model->depth); + } + }, + false); + view_free(app->view_measure); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_e); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_i); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSave); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewLoad); + variable_item_list_free(app->variable_item_list_config); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSubmenu); + submenu_free(app->submenu); + view_dispatcher_free(app->view_dispatcher); + furi_record_close(RECORD_GUI); + + free(app); +} + +int32_t main_key_copier_app(void *_p) { + UNUSED(_p); + + KeyCopierApp *app = key_copier_app_alloc(); + view_dispatcher_run(app->view_dispatcher); + + key_copier_app_free(app); + return 0; +} diff --git a/key_formats.c b/key_formats.c index 574b03c..d542f41 100644 --- a/key_formats.c +++ b/key_formats.c @@ -1,44 +1,223 @@ -#include "key_formats.h" -// all lengths in inches since it's all American formats -// angle is in degrees -const KeyFormat all_formats[] = { - { - .manufacturer = "Kwikset", - .format_name = "KW1", - .format_link = "https://lsamichigan.org/Tech/Kwikset_KeySpecs.pdf", - .first_pin_inch = 0.247, - .last_pin_inch = 0.847, - .pin_increment_inch = 0.15, - .pin_num = 5, - .pin_width_inch = 0.084, - .elbow_inch = 0.15, - .drill_angle = 90, - .uncut_depth_inch = 0.329, - .deepest_depth_inch = 0.191, - .depth_step_inch = 0.023, - .min_depth_ind = 1, - .max_depth_ind = 7, - .macs = 4, - .clearance = 3 - }, - - { - .manufacturer = "Schlage", - .format_name = "SC4", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", - .first_pin_inch = 0.231, - .last_pin_inch = 1.012, - .pin_increment_inch = 0.1562, - .pin_num = 6, - .pin_width_inch = 0.031, - .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make 100 degrees very ugly and unsuable - .uncut_depth_inch = 0.335, - .deepest_depth_inch = 0.2, - .depth_step_inch = 0.015, - .min_depth_ind = 0, - .max_depth_ind = 9, - .macs = 7, - .clearance = 8 - } -}; +#include "key_formats.h" +// all lengths in inches since it's all American formats +// angle is in degrees +const KeyFormat all_formats[] = { + {.manufacturer = "Kwikset", + .format_name = "KW1", + + .format_link = "https://lsamichigan.org/Tech/Kwikset_KeySpecs.pdf", + .first_pin_inch = 0.247, + .last_pin_inch = 0.847, + .pin_increment_inch = 0.15, + .pin_num = 5, + .pin_width_inch = 0.084, + .elbow_inch = 0.15, + .drill_angle = 90, + .uncut_depth_inch = 0.329, + .deepest_depth_inch = 0.191, + .depth_step_inch = 0.023, + .min_depth_ind = 1, + .max_depth_ind = 7, + .macs = 4, + .clearance = 3}, + + {.manufacturer = "Schlage", + .format_name = "SC4", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.231, + .last_pin_inch = 1.012, + .pin_increment_inch = 0.1562, + .pin_num = 6, + .pin_width_inch = 0.031, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.335, + .deepest_depth_inch = 0.2, + .depth_step_inch = 0.015, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Arrow", + .format_name = "AR4", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.265, + .last_pin_inch = 1.040, + .pin_increment_inch = 0.155, + .pin_num = 6, + .pin_width_inch = 0.060, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will + // make 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.312, + .deepest_depth_inch = 0.186, + .depth_step_inch = 0.014, + .min_depth_ind = 0, + .max_depth_ind = 10, + .macs = 6, + .clearance = 8}, + + {.manufacturer = "Master Lock", + .format_name = "M1", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.185, + .last_pin_inch = 0.689, + .pin_increment_inch = 0.126, + .pin_num = 5, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.276, + .deepest_depth_inch = 0.171, + .depth_step_inch = 0.015, + .min_depth_ind = 0, + .max_depth_ind = 7, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "American", + .format_name = "AM7", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.157, + .last_pin_inch = 0.781, + .pin_increment_inch = 0.125, + .pin_num = 6, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.283, + .deepest_depth_inch = 0.173, + .depth_step_inch = 0.016, + .min_depth_ind = 0, + .max_depth_ind = 8, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Yale", + .format_name = "Y2", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.200, + .last_pin_inch = 1.025, + .pin_increment_inch = 0.165, + .pin_num = 6, + .pin_width_inch = 0.054, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.320, + .deepest_depth_inch = 0.145, + .depth_step_inch = 0.025, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 9, + .clearance = 1}, + + {.manufacturer = "Yale", + .format_name = "Y11", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.124, + .last_pin_inch = 0.502, + .pin_increment_inch = 0.095, + .pin_num = 5, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.246, + .deepest_depth_inch = 0.167, + .depth_step_inch = 0.020, + .min_depth_ind = 0, + .max_depth_ind = 5, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Sargent", + .format_name = "S22", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.216, + .last_pin_inch = 0.996, + .pin_increment_inch = 0.156, + .pin_num = 6, + .pin_width_inch = 0.063, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.328, + .deepest_depth_inch = 0.148, + .depth_step_inch = 0.020, + .min_depth_ind = 0, + .max_depth_ind = 10, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "National", + .format_name = "NA25", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.250, + .last_pin_inch = 0.874, + .pin_increment_inch = 0.156, + .pin_num = 5, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.304, + .deepest_depth_inch = 0.191, + .depth_step_inch = 0.012, + .min_depth_ind = 0, + .max_depth_ind = 10, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Corbin", + .format_name = "CO88", + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.250, + .last_pin_inch = 1.030, + .pin_increment_inch = 0.156, + .pin_num = 6, + .pin_width_inch = 0.047, + .elbow_inch = 0.1, + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.343, + .deepest_depth_inch = 0.217, + .depth_step_inch = 0.014, + .min_depth_ind = 0, + .max_depth_ind = 10, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Ford", + .format_name = "H75", + .sides = 2, + .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .first_pin_inch = 0.201, + .last_pin_inch = 0.845, + .pin_increment_inch = 0.092, + .pin_num = 8, + .pin_width_inch = 0.039, + .elbow_inch = 0.201, // + .drill_angle = + 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.354, + .deepest_depth_inch = 0.254, + .depth_step_inch = 0.025, + .min_depth_ind = 0, + .max_depth_ind = 5, + .macs = 5, + .clearance = 0}}; diff --git a/key_formats.h b/key_formats.h index 24dcc44..0a1da01 100644 --- a/key_formats.h +++ b/key_formats.h @@ -1,31 +1,31 @@ -#ifndef KEY_FORMATS_H -#define KEY_FORMATS_H - -#define FORMAT_NUM 2 - -typedef struct { - char* manufacturer; - char* format_name; - char* format_link; - - double first_pin_inch; - double last_pin_inch; - double pin_increment_inch; - int pin_num; - double pin_width_inch; - double drill_angle; - double elbow_inch; - - double uncut_depth_inch; - double deepest_depth_inch; - double depth_step_inch; - int min_depth_ind; - int max_depth_ind; - - int macs; - int clearance; -} KeyFormat; - -extern const KeyFormat all_formats[FORMAT_NUM]; - -#endif // KEY_FORMATS_H +#ifndef KEY_FORMATS_H +#define KEY_FORMATS_H + +#define FORMAT_NUM 11 + +typedef struct { + char *manufacturer; + char *format_name; + char *format_link; + + double first_pin_inch; + double last_pin_inch; + double pin_increment_inch; + int pin_num; + double pin_width_inch; + double drill_angle; + double elbow_inch; + + double uncut_depth_inch; + double deepest_depth_inch; + double depth_step_inch; + int min_depth_ind; + int max_depth_ind; + + int macs; + int clearance; +} KeyFormat; + +extern const KeyFormat all_formats[FORMAT_NUM]; + +#endif // KEY_FORMATS_H From 43f469d825bc65eba68563db6c00002f267891b8 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Sun, 12 Jan 2025 21:16:11 -0700 Subject: [PATCH 02/15] FinalbugFixes and added tip stop to the right --- key_copier.c | 28 ++++++++++++++++++---------- key_formats.c | 5 +++-- key_formats.h | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/key_copier.c b/key_copier.c index 9a357b3..f6ec8cc 100644 --- a/key_copier.c +++ b/key_copier.c @@ -447,11 +447,13 @@ static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { } // new end - canvas_draw_line( - canvas, pin_center_px - pin_half_width_px, - bottom_contour_px - current_depth_px, pin_center_px + pin_half_width_px, - bottom_contour_px - - current_depth_px); // draw bottom pin width horizontal line + // canvas_draw_line( + // canvas, + // pin_center_px - pin_half_width_px, + // bottom_contour_px - current_depth_px, + // pin_center_px + pin_half_width_px, + // bottom_contour_px - current_depth_px); // draw bottom pin width + // horizontal line int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; @@ -462,10 +464,13 @@ static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { last_depth = 0; pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); - canvas_draw_line( - canvas, 0, bottom_contour_px, - pin_center_px - pin_half_width_px - current_depth_px, - bottom_contour_px); // draw bottom shoulder (hidden by level contour) + // canvas_draw_line( + // canvas, + // 0, + // bottom_contour_px, + // pin_center_px - pin_half_width_px - current_depth_px, + // bottom_contour_px); // draw bottom shoulder (hidden by + // level contour) } if (current_pin == my_model->format.pin_num) { next_depth = 0; @@ -531,7 +536,10 @@ static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { canvas_draw_line(canvas, 0, 62, level_contour_px, 62); canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, 62 - elbow_px); - canvas_draw_line(canvas, 1, 1, 1, 63); + + canvas_draw_line( + canvas, level_contour_px, 20, level_contour_px, + 63); // change to if stop ==tip and measure from this point back. int slc_pin_px = (int)round((my_format.first_pin_inch + diff --git a/key_formats.c b/key_formats.c index d542f41..a663341 100644 --- a/key_formats.c +++ b/key_formats.c @@ -153,7 +153,7 @@ const KeyFormat all_formats[] = { .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable - .uncut_depth_inch = 0.328, + .uncut_depth_inch = 0.328, // double check .deepest_depth_inch = 0.148, .depth_step_inch = 0.020, .min_depth_ind = 0, @@ -210,7 +210,8 @@ const KeyFormat all_formats[] = { .pin_increment_inch = 0.092, .pin_num = 8, .pin_width_inch = 0.039, - .elbow_inch = 0.201, // + .elbow_inch = 0.201, // this should be equal to first pin inch for tip + // stopped key line .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable diff --git a/key_formats.h b/key_formats.h index 0a1da01..174c39f 100644 --- a/key_formats.h +++ b/key_formats.h @@ -7,7 +7,7 @@ typedef struct { char *manufacturer; char *format_name; char *format_link; - + int sides; double first_pin_inch; double last_pin_inch; double pin_increment_inch; From a0f6a47abba3ec381fad89f6b01129d17cd9dd9d Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Sun, 12 Jan 2025 21:36:04 -0700 Subject: [PATCH 03/15] Added LW4 LW5 from fork --- key_formats.c | 68 +++++++++++++++++++++++++++++++++++---------------- key_formats.h | 38 ++++++++++++++-------------- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/key_formats.c b/key_formats.c index a663341..401677d 100644 --- a/key_formats.c +++ b/key_formats.c @@ -30,8 +30,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.031, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.335, .deepest_depth_inch = 0.2, @@ -50,8 +49,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.060, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will + .drill_angle = 90, // This should actually be 100 but the current resolution will // make 100 degrees very ugly and unsuable .uncut_depth_inch = 0.312, .deepest_depth_inch = 0.186, @@ -70,8 +68,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.276, .deepest_depth_inch = 0.171, @@ -90,8 +87,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.283, .deepest_depth_inch = 0.173, @@ -110,8 +106,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.320, .deepest_depth_inch = 0.145, @@ -130,8 +125,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.246, .deepest_depth_inch = 0.167, @@ -150,8 +144,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.063, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.328, // double check .deepest_depth_inch = 0.148, @@ -170,8 +163,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.304, .deepest_depth_inch = 0.191, @@ -190,8 +182,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.047, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.343, .deepest_depth_inch = 0.217, @@ -201,6 +192,42 @@ const KeyFormat all_formats[] = { .macs = 7, .clearance = 8}, + {.manufacturer = "Lockwood", + .format_name = "LW4", + .format_link = "", + .first_pin_inch = 0.245, + .last_pin_inch = 0.870, + .pin_increment_inch = 0.1562, + .pin_num = 5, + .pin_width_inch = 0.031, + .elbow_inch = 0.1, + .drill_angle = 90, + .uncut_depth_inch = 0.344, + .deepest_depth_inch = 0.203, + .depth_step_inch = 0.014, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 9, + .clearance = 8}, + + {.manufacturer = "Lockwood", + .format_name = "LW5", + .format_link = "", + .first_pin_inch = 0.245, + .last_pin_inch = 1.0262, + .pin_increment_inch = 0.1562, + .pin_num = 6, + .pin_width_inch = 0.031, + .elbow_inch = 0.1, + .drill_angle = 90, + .uncut_depth_inch = 0.344, + .deepest_depth_inch = 0.203, + .depth_step_inch = 0.014, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 9, + .clearance = 8}, + {.manufacturer = "Ford", .format_name = "H75", .sides = 2, @@ -211,9 +238,8 @@ const KeyFormat all_formats[] = { .pin_num = 8, .pin_width_inch = 0.039, .elbow_inch = 0.201, // this should be equal to first pin inch for tip - // stopped key line - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.354, .deepest_depth_inch = 0.254, diff --git a/key_formats.h b/key_formats.h index 174c39f..31ffb00 100644 --- a/key_formats.h +++ b/key_formats.h @@ -1,29 +1,29 @@ #ifndef KEY_FORMATS_H #define KEY_FORMATS_H -#define FORMAT_NUM 11 +#define FORMAT_NUM 13 typedef struct { - char *manufacturer; - char *format_name; - char *format_link; - int sides; - double first_pin_inch; - double last_pin_inch; - double pin_increment_inch; - int pin_num; - double pin_width_inch; - double drill_angle; - double elbow_inch; + char* manufacturer; + char* format_name; + char* format_link; + int sides; + double first_pin_inch; + double last_pin_inch; + double pin_increment_inch; + int pin_num; + double pin_width_inch; + double drill_angle; + double elbow_inch; - double uncut_depth_inch; - double deepest_depth_inch; - double depth_step_inch; - int min_depth_ind; - int max_depth_ind; + double uncut_depth_inch; + double deepest_depth_inch; + double depth_step_inch; + int min_depth_ind; + int max_depth_ind; - int macs; - int clearance; + int macs; + int clearance; } KeyFormat; extern const KeyFormat all_formats[FORMAT_NUM]; From 13f98fd59036ff257dd0cee06ad911cfeb82b7a5 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Mon, 13 Jan 2025 01:24:15 -0700 Subject: [PATCH 04/15] Format stops added --- key_copier.c | 12 +++++++++--- key_formats.c | 31 +++++++++++++++++++++---------- key_formats.h | 37 +++++++++++++++++++------------------ 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/key_copier.c b/key_copier.c index f6ec8cc..bbc8d57 100644 --- a/key_copier.c +++ b/key_copier.c @@ -537,9 +537,15 @@ static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, 62 - elbow_px); - canvas_draw_line( - canvas, level_contour_px, 20, level_contour_px, - 63); // change to if stop ==tip and measure from this point back. + if (my_format.stop == 2) { + // Draw a line using level_contour_px if stop equals tip + canvas_draw_line( + canvas, level_contour_px, top_contour_px, level_contour_px, + 63); // change to if stop ==tip and measure from this point back. + } else { + // Otherwise, draw a default line + canvas_draw_line(canvas, 1, top_contour_px, 1, 63); + } int slc_pin_px = (int)round((my_format.first_pin_inch + diff --git a/key_formats.c b/key_formats.c index 401677d..edab249 100644 --- a/key_formats.c +++ b/key_formats.c @@ -30,7 +30,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.031, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.335, .deepest_depth_inch = 0.2, @@ -49,7 +50,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.060, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will + .drill_angle = + 90, // This should actually be 100 but the current resolution will // make 100 degrees very ugly and unsuable .uncut_depth_inch = 0.312, .deepest_depth_inch = 0.186, @@ -68,7 +70,8 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.276, .deepest_depth_inch = 0.171, @@ -87,7 +90,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.283, .deepest_depth_inch = 0.173, @@ -106,7 +110,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.320, .deepest_depth_inch = 0.145, @@ -125,7 +130,8 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.246, .deepest_depth_inch = 0.167, @@ -144,7 +150,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.063, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.328, // double check .deepest_depth_inch = 0.148, @@ -163,7 +170,8 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.304, .deepest_depth_inch = 0.191, @@ -182,7 +190,8 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.047, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.343, .deepest_depth_inch = 0.217, @@ -231,6 +240,7 @@ const KeyFormat all_formats[] = { {.manufacturer = "Ford", .format_name = "H75", .sides = 2, + .stop = 2, .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", .first_pin_inch = 0.201, .last_pin_inch = 0.845, @@ -239,7 +249,8 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.201, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make + .drill_angle = + 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.354, .deepest_depth_inch = 0.254, diff --git a/key_formats.h b/key_formats.h index 31ffb00..20df3ca 100644 --- a/key_formats.h +++ b/key_formats.h @@ -4,26 +4,27 @@ #define FORMAT_NUM 13 typedef struct { - char* manufacturer; - char* format_name; - char* format_link; - int sides; - double first_pin_inch; - double last_pin_inch; - double pin_increment_inch; - int pin_num; - double pin_width_inch; - double drill_angle; - double elbow_inch; + char *manufacturer; + char *format_name; + char *format_link; + int sides; + int stop; + double first_pin_inch; + double last_pin_inch; + double pin_increment_inch; + int pin_num; + double pin_width_inch; + double drill_angle; + double elbow_inch; - double uncut_depth_inch; - double deepest_depth_inch; - double depth_step_inch; - int min_depth_ind; - int max_depth_ind; + double uncut_depth_inch; + double deepest_depth_inch; + double depth_step_inch; + int min_depth_ind; + int max_depth_ind; - int macs; - int clearance; + int macs; + int clearance; } KeyFormat; extern const KeyFormat all_formats[FORMAT_NUM]; From 8a2b6a9eeac8a4ea5ff9325400d79b71267f1e08 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Mon, 13 Jan 2025 02:20:55 -0700 Subject: [PATCH 05/15] old code removed stop added --- key_copier.c | 1436 +++++++++++++++++++++++++------------------------- 1 file changed, 705 insertions(+), 731 deletions(-) diff --git a/key_copier.c b/key_copier.c index bbc8d57..b40f06d 100644 --- a/key_copier.c +++ b/key_copier.c @@ -23,795 +23,769 @@ #define BACKLIGHT_ON 1 typedef enum { - KeyCopierSubmenuIndexMeasure, - KeyCopierSubmenuIndexConfigure, - KeyCopierSubmenuIndexSave, - KeyCopierSubmenuIndexLoad, - KeyCopierSubmenuIndexAbout, + KeyCopierSubmenuIndexMeasure, + KeyCopierSubmenuIndexConfigure, + KeyCopierSubmenuIndexSave, + KeyCopierSubmenuIndexLoad, + KeyCopierSubmenuIndexAbout, } KeyCopierSubmenuIndex; typedef enum { - KeyCopierViewSubmenu, - KeyCopierViewTextInput, - KeyCopierViewConfigure_i, - KeyCopierViewConfigure_e, - KeyCopierViewSave, - KeyCopierViewLoad, - KeyCopierViewMeasure, - KeyCopierViewAbout, + KeyCopierViewSubmenu, + KeyCopierViewTextInput, + KeyCopierViewConfigure_i, + KeyCopierViewConfigure_e, + KeyCopierViewSave, + KeyCopierViewLoad, + KeyCopierViewMeasure, + KeyCopierViewAbout, } KeyCopierView; typedef struct { - ViewDispatcher *view_dispatcher; - NotificationApp *notifications; - Submenu *submenu; - TextInput *text_input; - VariableItemList *variable_item_list_config; - View *view_measure; - View *view_config_e; - View *view_save; - View *view_load; - Widget *widget_about; - VariableItem *key_name_item; - VariableItem *format_item; - char *temp_buffer; - uint32_t temp_buffer_size; - - DialogsApp *dialogs; - FuriString *file_path; + ViewDispatcher* view_dispatcher; + NotificationApp* notifications; + Submenu* submenu; + TextInput* text_input; + VariableItemList* variable_item_list_config; + View* view_measure; + View* view_config_e; + View* view_save; + View* view_load; + Widget* widget_about; + VariableItem* key_name_item; + VariableItem* format_item; + char* temp_buffer; + uint32_t temp_buffer_size; + + DialogsApp* dialogs; + FuriString* file_path; } KeyCopierApp; typedef struct { - uint32_t format_index; - FuriString *key_name_str; - uint8_t pin_slc; // The pin that is being adjusted - uint8_t *depth; // The cutting depth - bool data_loaded; - KeyFormat format; + uint32_t format_index; + FuriString* key_name_str; + uint8_t pin_slc; // The pin that is being adjusted + uint8_t* depth; // The cutting depth + bool data_loaded; + KeyFormat format; } KeyCopierModel; -void initialize_model(KeyCopierModel *model) { - if (model->depth != NULL) { - free(model->depth); - } - model->format_index = 0; - memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); - model->depth = - (uint8_t *)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); - for (uint8_t i = 0; i <= model->format.pin_num; i++) { - model->depth[i] = model->format.min_depth_ind; - } - model->pin_slc = 1; - model->data_loaded = 0; - model->key_name_str = furi_string_alloc(); +void initialize_model(KeyCopierModel* model) { + if(model->depth != NULL) { + free(model->depth); + } + model->format_index = 0; + memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); + model->depth = (uint8_t*)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); + for(uint8_t i = 0; i <= model->format.pin_num; i++) { + model->depth[i] = model->format.min_depth_ind; + } + model->pin_slc = 1; + model->data_loaded = 0; + model->key_name_str = furi_string_alloc(); } -static uint32_t key_copier_navigation_exit_callback(void *_context) { - UNUSED(_context); - return VIEW_NONE; +static uint32_t key_copier_navigation_exit_callback(void* _context) { + UNUSED(_context); + return VIEW_NONE; } -static uint32_t key_copier_navigation_submenu_callback(void *_context) { - UNUSED(_context); - return KeyCopierViewSubmenu; +static uint32_t key_copier_navigation_submenu_callback(void* _context) { + UNUSED(_context); + return KeyCopierViewSubmenu; } -static void key_copier_submenu_callback(void *context, uint32_t index) { - KeyCopierApp *app = (KeyCopierApp *)context; - switch (index) { - case KeyCopierSubmenuIndexMeasure: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewMeasure); - break; - case KeyCopierSubmenuIndexConfigure: - view_dispatcher_switch_to_view(app->view_dispatcher, - KeyCopierViewConfigure_e); - break; - case KeyCopierSubmenuIndexSave: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSave); - break; - case KeyCopierSubmenuIndexLoad: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewLoad); - break; - case KeyCopierSubmenuIndexAbout: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewAbout); - break; - default: - break; - } +static void key_copier_submenu_callback(void* context, uint32_t index) { + KeyCopierApp* app = (KeyCopierApp*)context; + switch(index) { + case KeyCopierSubmenuIndexMeasure: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewMeasure); + break; + case KeyCopierSubmenuIndexConfigure: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure_e); + break; + case KeyCopierSubmenuIndexSave: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSave); + break; + case KeyCopierSubmenuIndexLoad: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewLoad); + break; + case KeyCopierSubmenuIndexAbout: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewAbout); + break; + default: + break; + } } -char *manufacturers[COUNT_OF(all_formats)]; -void initialize_manufacturers(char **manufacturers) { - // Populate the manufacturers array - for (size_t i = 0; i < COUNT_OF(all_formats); i++) { - manufacturers[i] = all_formats[i].manufacturer; - } +char* manufacturers[COUNT_OF(all_formats)]; +void initialize_manufacturers(char** manufacturers) { + // Populate the manufacturers array + for(size_t i = 0; i < COUNT_OF(all_formats); i++) { + manufacturers[i] = all_formats[i].manufacturer; + } } -static void key_copier_format_change(VariableItem *item) { - KeyCopierApp *app = variable_item_get_context(item); - KeyCopierModel *model = view_get_model(app->view_measure); - if (model->data_loaded) { - variable_item_set_current_value_index(item, model->format_index); - } - uint8_t format_index = variable_item_get_current_value_index(item); - if (format_index != model->format_index) { - model->format_index = format_index; - model->format = all_formats[format_index]; - if (model->depth != NULL) { - free(model->depth); +static void key_copier_format_change(VariableItem* item) { + KeyCopierApp* app = variable_item_get_context(item); + KeyCopierModel* model = view_get_model(app->view_measure); + if(model->data_loaded) { + variable_item_set_current_value_index(item, model->format_index); } - model->depth = - (uint8_t *)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); - for (uint8_t i = 0; i <= model->format.pin_num; i++) { - model->depth[i] = model->format.min_depth_ind; + uint8_t format_index = variable_item_get_current_value_index(item); + if(format_index != model->format_index) { + model->format_index = format_index; + model->format = all_formats[format_index]; + if(model->depth != NULL) { + free(model->depth); + } + model->depth = (uint8_t*)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); + for(uint8_t i = 0; i <= model->format.pin_num; i++) { + model->depth[i] = model->format.min_depth_ind; + } + model->pin_slc = 1; } - model->pin_slc = 1; - } - model->data_loaded = false; - variable_item_set_current_value_text(item, model->format.format_name); - model->format = all_formats[model->format_index]; + model->data_loaded = false; + variable_item_set_current_value_text(item, model->format.format_name); + model->format = all_formats[model->format_index]; } -static const char *format_config_label = "Key Format"; -static void key_copier_config_enter_callback(void *context) { - KeyCopierApp *app = (KeyCopierApp *)context; - KeyCopierModel *my_model = view_get_model(app->view_measure); - variable_item_list_reset(app->variable_item_list_config); - // Recreate this view every time we enter it so that it's always updated - app->format_item = variable_item_list_add( - app->variable_item_list_config, format_config_label, - COUNT_OF(all_formats), key_copier_format_change, app); - - View *view_config_i = - variable_item_list_get_view(app->variable_item_list_config); - variable_item_set_current_value_index(app->format_item, - my_model->format_index); - key_copier_format_change(app->format_item); - view_set_previous_callback(view_config_i, - key_copier_navigation_submenu_callback); - view_dispatcher_remove_view(app->view_dispatcher, - KeyCopierViewConfigure_i); // delete the last one - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, - view_config_i); - view_dispatcher_switch_to_view(app->view_dispatcher, - KeyCopierViewConfigure_i); // recreate it +static const char* format_config_label = "Key Format"; +static void key_copier_config_enter_callback(void* context) { + KeyCopierApp* app = (KeyCopierApp*)context; + KeyCopierModel* my_model = view_get_model(app->view_measure); + variable_item_list_reset(app->variable_item_list_config); + // Recreate this view every time we enter it so that it's always updated + app->format_item = variable_item_list_add( + app->variable_item_list_config, + format_config_label, + COUNT_OF(all_formats), + key_copier_format_change, + app); + + View* view_config_i = variable_item_list_get_view(app->variable_item_list_config); + variable_item_set_current_value_index(app->format_item, my_model->format_index); + key_copier_format_change(app->format_item); + view_set_previous_callback(view_config_i, key_copier_navigation_submenu_callback); + view_dispatcher_remove_view( + app->view_dispatcher, + KeyCopierViewConfigure_i); // delete the last one + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, view_config_i); + view_dispatcher_switch_to_view(app->view_dispatcher, + KeyCopierViewConfigure_i); // recreate it } -static const char *key_name_entry_text = "Enter name"; -static void key_copier_file_saver(void *context) { - KeyCopierApp *app = (KeyCopierApp *)context; - KeyCopierModel *model = view_get_model(app->view_measure); - bool redraw = true; - with_view_model( - app->view_measure, KeyCopierModel * model, - { furi_string_set(model->key_name_str, app->temp_buffer); }, redraw); - FuriString *file_path = furi_string_alloc(); - furi_string_printf(file_path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, - furi_string_get_cstr(model->key_name_str), - KEY_COPIER_FILE_EXTENSION); - - Storage *storage = furi_record_open(RECORD_STORAGE); - storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); - FURI_LOG_D(TAG, "mkdir finished"); - FlipperFormat *flipper_format = flipper_format_file_alloc(storage); - do { - const uint32_t version = 1; - const uint32_t pin_num_buffer = (uint32_t)model->format.pin_num; - const uint32_t macs_buffer = (uint32_t)model->format.macs; - FuriString *buffer = furi_string_alloc(); - if (!flipper_format_file_open_always(flipper_format, - furi_string_get_cstr(file_path))) - break; - if (!flipper_format_write_header_cstr(flipper_format, - "Flipper Key Copier File", version)) - break; - if (!flipper_format_write_string_cstr(flipper_format, "Manufacturer", - model->format.manufacturer)) - break; - if (!flipper_format_write_string_cstr(flipper_format, "Format Name", - model->format.format_name)) - break; - if (!flipper_format_write_string_cstr(flipper_format, "Data Sheet", - model->format.format_link)) - break; - if (!flipper_format_write_uint32(flipper_format, "Number of Pins", - &pin_num_buffer, 1)) - break; - if (!flipper_format_write_uint32( - flipper_format, "Maximum Adjacent Cut Specification (MACS)", - &macs_buffer, 1)) - break; - for (int i = 0; i < model->format.pin_num; i++) { - if (i < model->format.pin_num - 1) { - furi_string_cat_printf(buffer, "%d-", model->depth[i]); - } else { - furi_string_cat_printf(buffer, "%d", model->depth[i]); - } - } - if (!flipper_format_write_string(flipper_format, "Bitting Pattern", buffer)) - break; - furi_string_free(buffer); - // signal that the file was written successfully - } while (0); - flipper_format_free(flipper_format); +static const char* key_name_entry_text = "Enter name"; +static void key_copier_file_saver(void* context) { + KeyCopierApp* app = (KeyCopierApp*)context; + KeyCopierModel* model = view_get_model(app->view_measure); + bool redraw = true; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { furi_string_set(model->key_name_str, app->temp_buffer); }, + redraw); + FuriString* file_path = furi_string_alloc(); + furi_string_printf( + file_path, + "%s/%s%s", + STORAGE_APP_DATA_PATH_PREFIX, + furi_string_get_cstr(model->key_name_str), + KEY_COPIER_FILE_EXTENSION); + + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); + FURI_LOG_D(TAG, "mkdir finished"); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + do { + const uint32_t version = 1; + const uint32_t pin_num_buffer = (uint32_t)model->format.pin_num; + const uint32_t macs_buffer = (uint32_t)model->format.macs; + FuriString* buffer = furi_string_alloc(); + if(!flipper_format_file_open_always(flipper_format, furi_string_get_cstr(file_path))) + break; + if(!flipper_format_write_header_cstr(flipper_format, "Flipper Key Copier File", version)) + break; + if(!flipper_format_write_string_cstr( + flipper_format, "Manufacturer", model->format.manufacturer)) + break; + if(!flipper_format_write_string_cstr( + flipper_format, "Format Name", model->format.format_name)) + break; + if(!flipper_format_write_string_cstr( + flipper_format, "Data Sheet", model->format.format_link)) + break; + if(!flipper_format_write_uint32(flipper_format, "Number of Pins", &pin_num_buffer, 1)) + break; + if(!flipper_format_write_uint32( + flipper_format, "Maximum Adjacent Cut Specification (MACS)", &macs_buffer, 1)) + break; + for(int i = 0; i < model->format.pin_num; i++) { + if(i < model->format.pin_num - 1) { + furi_string_cat_printf(buffer, "%d-", model->depth[i]); + } else { + furi_string_cat_printf(buffer, "%d", model->depth[i]); + } + } + if(!flipper_format_write_string(flipper_format, "Bitting Pattern", buffer)) break; + furi_string_free(buffer); + // signal that the file was written successfully + } while(0); + flipper_format_free(flipper_format); - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); } -static void key_copier_view_save_callback(void *context) { - KeyCopierApp *app = (KeyCopierApp *)context; - // Header to display on the text input screen. - text_input_set_header_text(app->text_input, key_name_entry_text); - - // Copy the current name into the temporary buffer. - bool redraw = false; - with_view_model( - app->view_measure, KeyCopierModel * model, - { - strncpy(app->temp_buffer, furi_string_get_cstr(model->key_name_str), +static void key_copier_view_save_callback(void* context) { + KeyCopierApp* app = (KeyCopierApp*)context; + // Header to display on the text input screen. + text_input_set_header_text(app->text_input, key_name_entry_text); + + // Copy the current name into the temporary buffer. + bool redraw = false; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + strncpy( + app->temp_buffer, + furi_string_get_cstr(model->key_name_str), app->temp_buffer_size); - }, - redraw); - - // Configure the text input. When user enters text and clicks OK, - // key_copier_file_saver be called. - bool clear_previous_text = false; - text_input_set_result_callback(app->text_input, key_copier_file_saver, app, - app->temp_buffer, app->temp_buffer_size, - clear_previous_text); + }, + redraw); + + // Configure the text input. When user enters text and clicks OK, + // key_copier_file_saver be called. + bool clear_previous_text = false; + text_input_set_result_callback( + app->text_input, + key_copier_file_saver, + app, + app->temp_buffer, + app->temp_buffer_size, + clear_previous_text); + + view_set_previous_callback( + text_input_get_view(app->text_input), key_copier_navigation_submenu_callback); + + // Show text input dialog. + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); +} - view_set_previous_callback(text_input_get_view(app->text_input), - key_copier_navigation_submenu_callback); +static void key_copier_view_load_callback(void* context) { + KeyCopierApp* app = (KeyCopierApp*)context; + KeyCopierModel* model = view_get_model(app->view_measure); + DialogsFileBrowserOptions browser_options; + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); + dialog_file_browser_set_basic_options(&browser_options, KEY_COPIER_FILE_EXTENSION, &I_icon); + browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; + furi_string_set(app->file_path, browser_options.base_path); + if(dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) { + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + do { + if(!flipper_format_file_open_existing( + flipper_format, furi_string_get_cstr(app->file_path))) + break; + FuriString* format_buffer = furi_string_alloc(); + FuriString* depth_buffer = furi_string_alloc(); + if(!flipper_format_read_string(flipper_format, "Format Name", format_buffer)) break; + if(!flipper_format_read_string(flipper_format, "Bitting Pattern", depth_buffer)) break; + for(size_t i = 0; i < COUNT_OF(all_formats); i++) { + if(!strcmp(furi_string_get_cstr(format_buffer), all_formats[i].format_name)) { + model->format_index = (uint32_t)i; + model->format = all_formats[model->format_index]; + } + } - // Show text input dialog. - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); + for(int i = 0; i < model->format.pin_num; i++) { + model->depth[i] = (uint8_t)(furi_string_get_char(depth_buffer, i * 2) - '0'); + } + model->data_loaded = true; + // signal that the file was read successfully + } while(0); + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + } + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); } -static void key_copier_view_load_callback(void *context) { - KeyCopierApp *app = (KeyCopierApp *)context; - KeyCopierModel *model = view_get_model(app->view_measure); - DialogsFileBrowserOptions browser_options; - Storage *storage = furi_record_open(RECORD_STORAGE); - storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); - dialog_file_browser_set_basic_options(&browser_options, - KEY_COPIER_FILE_EXTENSION, &I_icon); - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - furi_string_set(app->file_path, browser_options.base_path); - if (dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, - &browser_options)) { - FlipperFormat *flipper_format = flipper_format_file_alloc(storage); - do { - if (!flipper_format_file_open_existing( - flipper_format, furi_string_get_cstr(app->file_path))) - break; - FuriString *format_buffer = furi_string_alloc(); - FuriString *depth_buffer = furi_string_alloc(); - if (!flipper_format_read_string(flipper_format, "Format Name", - format_buffer)) - break; - if (!flipper_format_read_string(flipper_format, "Bitting Pattern", - depth_buffer)) - break; - for (size_t i = 0; i < COUNT_OF(all_formats); i++) { - if (!strcmp(furi_string_get_cstr(format_buffer), - all_formats[i].format_name)) { - model->format_index = (uint32_t)i; - model->format = all_formats[model->format_index]; - } - } - - for (int i = 0; i < model->format.pin_num; i++) { - model->depth[i] = - (uint8_t)(furi_string_get_char(depth_buffer, i * 2) - '0'); - } - model->data_loaded = true; - // signal that the file was read successfully - } while (0); - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - } - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); -} +static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { + static double inches_per_px = (double)INCHES_PER_PX; + canvas_set_bitmap_mode(canvas, true); + KeyCopierModel* my_model = (KeyCopierModel*)model; + KeyFormat my_format = my_model->format; + FuriString* buffer = furi_string_alloc(); + int pin_half_width_px = (int)round((my_format.pin_width_inch / inches_per_px) / 2); + int pin_step_px = (int)round(my_format.pin_increment_inch / inches_per_px); + double drill_radians = + (180 - my_format.drill_angle) / 2 / 180 * (double)M_PI; // Convert angle to radians + double tangent = tan(drill_radians); + int top_contour_px = (int)round(62 - my_format.uncut_depth_inch / inches_per_px); + int bottom_contour_px = 0; + + if(my_format.sides == 2) + bottom_contour_px = + top_contour_px + (int)round(my_format.uncut_depth_inch / inches_per_px); + int post_extra_x_px = 0; + int pre_extra_x_px = 0; + int bottom_post_extra_x_px = 0; // new + int bottom_pre_extra_x_px = 0; // new + for(int current_pin = 1; current_pin <= my_model->format.pin_num; current_pin += 1) { + double current_center_px = + my_format.first_pin_inch + (current_pin - 1) * my_format.pin_increment_inch; + int pin_center_px = (int)round(current_center_px / inches_per_px); + + furi_string_printf(buffer, "%d", my_model->depth[current_pin - 1]); + canvas_draw_str_aligned( + canvas, + pin_center_px, + top_contour_px - 12, + AlignCenter, + AlignCenter, + furi_string_get_cstr(buffer)); -static void key_copier_view_measure_draw_callback(Canvas *canvas, void *model) { - static double inches_per_px = (double)INCHES_PER_PX; - canvas_set_bitmap_mode(canvas, true); - KeyCopierModel *my_model = (KeyCopierModel *)model; - KeyFormat my_format = my_model->format; - FuriString *buffer = furi_string_alloc(); - int pin_half_width_px = - (int)round((my_format.pin_width_inch / inches_per_px) / 2); - int pin_step_px = (int)round(my_format.pin_increment_inch / inches_per_px); - double drill_radians = (180 - my_format.drill_angle) / 2 / 180 * - (double)M_PI; // Convert angle to radians - double tangent = tan(drill_radians); - int top_contour_px = - (int)round(62 - my_format.uncut_depth_inch / inches_per_px); - int bottom_contour_px = 0; - // int bottom_contour_px = - // top_contour_px + (int)round(my_format.uncut_depth_inch / - // inches_per_px); - if (my_format.sides == 2) - bottom_contour_px = - top_contour_px + (int)round(my_format.uncut_depth_inch / inches_per_px); - int post_extra_x_px = 0; - int pre_extra_x_px = 0; - int bottom_post_extra_x_px = 0; // new - int bottom_pre_extra_x_px = 0; // new - for (int current_pin = 1; current_pin <= my_model->format.pin_num; - current_pin += 1) { - double current_center_px = my_format.first_pin_inch + - (current_pin - 1) * my_format.pin_increment_inch; - int pin_center_px = (int)round(current_center_px / inches_per_px); - - furi_string_printf(buffer, "%d", my_model->depth[current_pin - 1]); - canvas_draw_str_aligned(canvas, pin_center_px, top_contour_px - 12, - AlignCenter, AlignCenter, - furi_string_get_cstr(buffer)); - - canvas_draw_line( - canvas, pin_center_px, top_contour_px - 5, pin_center_px, - top_contour_px); // the vertical line to indicate pin center - int current_depth = - my_model->depth[current_pin - 1] - my_format.min_depth_ind; - int current_depth_px = - (int)round(current_depth * my_format.depth_step_inch / inches_per_px); - canvas_draw_line( - canvas, pin_center_px - pin_half_width_px, - top_contour_px + current_depth_px, pin_center_px + pin_half_width_px, - top_contour_px + - current_depth_px); // draw top pin width horizontal line - - // if(my_format.sides == 2) //old (remove new start to end and remove // for - // this line to fix) - - if (my_format.sides == 2) { // new start - int last_depth = - my_model->depth[current_pin - 2] - my_format.min_depth_ind; - int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; - int current_depth = - my_model->depth[current_pin - 1] - my_format.min_depth_ind; - int current_depth_px = - (int)round(current_depth * my_format.depth_step_inch / inches_per_px); - - // Draw horizontal line for bottom pin - canvas_draw_line(canvas, pin_center_px - pin_half_width_px, - bottom_contour_px - current_depth_px, - pin_center_px + pin_half_width_px, - bottom_contour_px - current_depth_px); - - // Handle first pin for bottom - if (current_pin == 1) { - canvas_draw_line(canvas, 0, bottom_contour_px, - pin_center_px - pin_half_width_px - current_depth_px, - bottom_contour_px); - last_depth = 0; - bottom_pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); - } - - // Handle left side intersection for bottom - if ((last_depth + current_depth) > my_format.clearance) { - if (current_pin != 1) { - bottom_pre_extra_x_px = - min(max(pin_step_px - bottom_post_extra_x_px, pin_half_width_px), - pin_step_px - pin_half_width_px); - } - canvas_draw_line( - canvas, pin_center_px - bottom_pre_extra_x_px, - bottom_contour_px - - max((int)round((current_depth_px - - (bottom_pre_extra_x_px - pin_half_width_px)) * - tangent), - 0), - pin_center_px - pin_half_width_px, - bottom_contour_px - (int)round(current_depth_px * tangent)); - } else { - int last_depth_px = - (int)round(last_depth * my_format.depth_step_inch / inches_per_px); - int up_slope_start_x_px = - pin_center_px - pin_half_width_px - current_depth_px; - canvas_draw_line( - canvas, pin_center_px - pin_half_width_px - current_depth_px, - bottom_contour_px, pin_center_px - pin_half_width_px, - bottom_contour_px - (int)round(current_depth_px * tangent)); canvas_draw_line( canvas, - min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, - up_slope_start_x_px), - bottom_contour_px, up_slope_start_x_px, bottom_contour_px); - } - - // Handle right side intersection for bottom - if ((current_depth + next_depth) > my_format.clearance) { - double numerator = (double)current_depth; - double denominator = (double)(current_depth + next_depth); - double product = (numerator / denominator) * pin_step_px; - bottom_post_extra_x_px = (int)min(max(product, pin_half_width_px), - pin_step_px - pin_half_width_px); + pin_center_px, + top_contour_px - 5, + pin_center_px, + top_contour_px); // the vertical line to indicate pin center + int current_depth = my_model->depth[current_pin - 1] - my_format.min_depth_ind; + int current_depth_px = + (int)round(current_depth * my_format.depth_step_inch / inches_per_px); canvas_draw_line( - canvas, pin_center_px + pin_half_width_px, - bottom_contour_px - current_depth_px, - pin_center_px + bottom_post_extra_x_px, - bottom_contour_px - - max(current_depth_px - (int)round((bottom_post_extra_x_px - - pin_half_width_px) * - tangent), - 0)); - } else { - canvas_draw_line(canvas, pin_center_px + pin_half_width_px, - bottom_contour_px - - (int)round(current_depth_px * tangent), - pin_center_px + pin_half_width_px + current_depth_px, - bottom_contour_px); - } - } - // new end - - // canvas_draw_line( - // canvas, - // pin_center_px - pin_half_width_px, - // bottom_contour_px - current_depth_px, - // pin_center_px + pin_half_width_px, - // bottom_contour_px - current_depth_px); // draw bottom pin width - // horizontal line - - int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; - int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; - if (current_pin == 1) { - canvas_draw_line(canvas, 0, top_contour_px, - pin_center_px - pin_half_width_px - current_depth_px, - top_contour_px); // draw top shoulder - last_depth = 0; - pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); - - // canvas_draw_line( - // canvas, - // 0, - // bottom_contour_px, - // pin_center_px - pin_half_width_px - current_depth_px, - // bottom_contour_px); // draw bottom shoulder (hidden by - // level contour) - } - if (current_pin == my_model->format.pin_num) { - next_depth = 0; - } - if ((last_depth + current_depth) > my_format.clearance) { // yes - // intersection - - if (current_pin != 1) { - pre_extra_x_px = - min(max(pin_step_px - post_extra_x_px, pin_half_width_px), - pin_step_px - pin_half_width_px); - } - canvas_draw_line( - canvas, pin_center_px - pre_extra_x_px, - top_contour_px + - max((int)round((current_depth_px - - (pre_extra_x_px - pin_half_width_px)) * - tangent), - 0), - pin_center_px - pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent)); - } else { - int last_depth_px = - (int)round(last_depth * my_format.depth_step_inch / inches_per_px); - int down_slope_start_x_px = - pin_center_px - pin_half_width_px - current_depth_px; - canvas_draw_line(canvas, - pin_center_px - pin_half_width_px - current_depth_px, - top_contour_px, pin_center_px - pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent)); - canvas_draw_line( - canvas, - min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, - down_slope_start_x_px), - top_contour_px, down_slope_start_x_px, top_contour_px); - } - if ((current_depth + next_depth) > my_format.clearance) { // yes - // intersection - double numerator = (double)current_depth; - double denominator = (double)(current_depth + next_depth); - double product = (numerator / denominator) * pin_step_px; - post_extra_x_px = (int)min(max(product, pin_half_width_px), - pin_step_px - pin_half_width_px); - canvas_draw_line( - canvas, pin_center_px + pin_half_width_px, - top_contour_px + current_depth_px, pin_center_px + post_extra_x_px, - top_contour_px + - max(current_depth_px - - (int)round((post_extra_x_px - pin_half_width_px) * - tangent), - 0)); - } else { // no intersection - canvas_draw_line(canvas, pin_center_px + pin_half_width_px, - top_contour_px + (int)round(current_depth_px * tangent), - pin_center_px + pin_half_width_px + current_depth_px, - top_contour_px); - } - } - - int level_contour_px = (int)round( - (my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); - int elbow_px = (int)round(my_format.elbow_inch / inches_per_px); - canvas_draw_line(canvas, 0, 62, level_contour_px, 62); - canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, - 62 - elbow_px); - - if (my_format.stop == 2) { - // Draw a line using level_contour_px if stop equals tip - canvas_draw_line( - canvas, level_contour_px, top_contour_px, level_contour_px, - 63); // change to if stop ==tip and measure from this point back. - } else { - // Otherwise, draw a default line - canvas_draw_line(canvas, 1, top_contour_px, 1, 63); - } - - int slc_pin_px = - (int)round((my_format.first_pin_inch + - (my_model->pin_slc - 1) * my_format.pin_increment_inch) / - inches_per_px); - canvas_draw_icon(canvas, slc_pin_px - 2, top_contour_px - 25, &I_arrow_down); - - furi_string_printf(buffer, "%s", my_format.format_name); - canvas_draw_str(canvas, 100, 10, furi_string_get_cstr(buffer)); - furi_string_free(buffer); -} + canvas, + pin_center_px - pin_half_width_px, + top_contour_px + current_depth_px, + pin_center_px + pin_half_width_px, + top_contour_px + current_depth_px); // draw top pin width horizontal line + + if(my_format.sides == 2) { // new + int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; + int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; + int current_depth = my_model->depth[current_pin - 1] - my_format.min_depth_ind; + int current_depth_px = + (int)round(current_depth * my_format.depth_step_inch / inches_per_px); + + // Draw horizontal line for bottom pin + canvas_draw_line( + canvas, + pin_center_px - pin_half_width_px, + bottom_contour_px - current_depth_px, + pin_center_px + pin_half_width_px, + bottom_contour_px - current_depth_px); + + // Handle first pin for bottom + if(current_pin == 1) { + canvas_draw_line( + canvas, + 0, + bottom_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px); + last_depth = 0; + bottom_pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); + } -static bool key_copier_view_measure_input_callback(InputEvent *event, - void *context) { - KeyCopierApp *app = (KeyCopierApp *)context; - if (event->type == InputTypeShort) { - switch (event->key) { - case InputKeyLeft: { - bool redraw = true; - with_view_model( - app->view_measure, KeyCopierModel * model, - { - if (model->pin_slc > 1) { - model->pin_slc--; + // Handle left side intersection for bottom + if((last_depth + current_depth) > my_format.clearance) { + if(current_pin != 1) { + bottom_pre_extra_x_px = + min(max(pin_step_px - bottom_post_extra_x_px, pin_half_width_px), + pin_step_px - pin_half_width_px); + } + canvas_draw_line( + canvas, + pin_center_px - bottom_pre_extra_x_px, + bottom_contour_px - + max((int)round( + (current_depth_px - (bottom_pre_extra_x_px - pin_half_width_px)) * + tangent), + 0), + pin_center_px - pin_half_width_px, + bottom_contour_px - (int)round(current_depth_px * tangent)); + } else { + int last_depth_px = + (int)round(last_depth * my_format.depth_step_inch / inches_per_px); + int up_slope_start_x_px = pin_center_px - pin_half_width_px - current_depth_px; + canvas_draw_line( + canvas, + pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px, + pin_center_px - pin_half_width_px, + bottom_contour_px - (int)round(current_depth_px * tangent)); + canvas_draw_line( + canvas, + min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, + up_slope_start_x_px), + bottom_contour_px, + up_slope_start_x_px, + bottom_contour_px); } - }, - redraw); - break; - } - case InputKeyRight: { - bool redraw = true; - with_view_model( - app->view_measure, KeyCopierModel * model, - { - if (model->pin_slc < model->format.pin_num) { - model->pin_slc++; + + // Handle right side intersection for bottom + if((current_depth + next_depth) > my_format.clearance) { + double numerator = (double)current_depth; + double denominator = (double)(current_depth + next_depth); + double product = (numerator / denominator) * pin_step_px; + bottom_post_extra_x_px = + (int)min(max(product, pin_half_width_px), pin_step_px - pin_half_width_px); + canvas_draw_line( + canvas, + pin_center_px + pin_half_width_px, + bottom_contour_px - current_depth_px, + pin_center_px + bottom_post_extra_x_px, + bottom_contour_px - + max(current_depth_px - + (int)round((bottom_post_extra_x_px - pin_half_width_px) * tangent), + 0)); + } else { + canvas_draw_line( + canvas, + pin_center_px + pin_half_width_px, + bottom_contour_px - (int)round(current_depth_px * tangent), + pin_center_px + pin_half_width_px + current_depth_px, + bottom_contour_px); } - }, - redraw); - break; - } - case InputKeyUp: { - bool redraw = true; - with_view_model( - app->view_measure, KeyCopierModel * model, - { - if (model->depth[model->pin_slc - 1] > - model->format.min_depth_ind) { - if (model->pin_slc == - 1) { // first pin only limited by the next one - if (model->depth[model->pin_slc] - - model->depth[model->pin_slc - 1] < - model->format.macs) - model->depth[model->pin_slc - 1]--; - } else if (model->pin_slc == - model->format.pin_num) { // last pin only limited by - // the previous one - if (model->depth[model->pin_slc - 2] - - model->depth[model->pin_slc - 1] < - model->format.macs) { - model->depth[model->pin_slc - 1]--; - } - } else { - if (model->depth[model->pin_slc] - - model->depth[model->pin_slc - 1] < - model->format.macs && - model->depth[model->pin_slc - 2] - - model->depth[model->pin_slc - 1] < - model->format.macs) { - model->depth[model->pin_slc - 1]--; - } - } + } + // new end + + int last_depth = my_model->depth[current_pin - 2] - my_format.min_depth_ind; + int next_depth = my_model->depth[current_pin] - my_format.min_depth_ind; + if(current_pin == 1) { + canvas_draw_line( + canvas, + 0, + top_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + top_contour_px); // draw top shoulder + last_depth = 0; + pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); + } + if(current_pin == my_model->format.pin_num) { + next_depth = 0; + } + if((last_depth + current_depth) > my_format.clearance) { // yes + // intersection + + if(current_pin != 1) { + pre_extra_x_px = + min(max(pin_step_px - post_extra_x_px, pin_half_width_px), + pin_step_px - pin_half_width_px); } - }, - redraw); - break; + canvas_draw_line( + canvas, + pin_center_px - pre_extra_x_px, + top_contour_px + + max((int)round( + (current_depth_px - (pre_extra_x_px - pin_half_width_px)) * tangent), + 0), + pin_center_px - pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent)); + } else { + int last_depth_px = (int)round(last_depth * my_format.depth_step_inch / inches_per_px); + int down_slope_start_x_px = pin_center_px - pin_half_width_px - current_depth_px; + canvas_draw_line( + canvas, + pin_center_px - pin_half_width_px - current_depth_px, + top_contour_px, + pin_center_px - pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent)); + canvas_draw_line( + canvas, + min(pin_center_px - pin_step_px + pin_half_width_px + last_depth_px, + down_slope_start_x_px), + top_contour_px, + down_slope_start_x_px, + top_contour_px); + } + if((current_depth + next_depth) > my_format.clearance) { // yes + // intersection + double numerator = (double)current_depth; + double denominator = (double)(current_depth + next_depth); + double product = (numerator / denominator) * pin_step_px; + post_extra_x_px = + (int)min(max(product, pin_half_width_px), pin_step_px - pin_half_width_px); + canvas_draw_line( + canvas, + pin_center_px + pin_half_width_px, + top_contour_px + current_depth_px, + pin_center_px + post_extra_x_px, + top_contour_px + + max(current_depth_px - + (int)round((post_extra_x_px - pin_half_width_px) * tangent), + 0)); + } else { // no intersection + canvas_draw_line( + canvas, + pin_center_px + pin_half_width_px, + top_contour_px + (int)round(current_depth_px * tangent), + pin_center_px + pin_half_width_px + current_depth_px, + top_contour_px); + } } - case InputKeyDown: { - bool redraw = true; - with_view_model( - app->view_measure, KeyCopierModel * model, - { - if (model->depth[model->pin_slc - 1] < - model->format.max_depth_ind) { - if (model->pin_slc == - 1) { // first pin only limited by the next one - if (model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc] < - model->format.macs) - model->depth[model->pin_slc - 1]++; - } else if (model->pin_slc == - model->format.pin_num) { // last pin only limited by - // the previous one - if (model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc - 2] < - model->format.macs) { - model->depth[model->pin_slc - 1]++; - } - } else { - if (model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc] < - model->format.macs && - model->depth[model->pin_slc - 1] - - model->depth[model->pin_slc - 2] < - model->format.macs) { - model->depth[model->pin_slc - 1]++; - } - } - } - }, - redraw); - break; + + int level_contour_px = + (int)round((my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); + int elbow_px = (int)round(my_format.elbow_inch / inches_per_px); + canvas_draw_line(canvas, 0, 62, level_contour_px, 62); + canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, 62 - elbow_px); + + if(my_format.stop == 2) { + // Draw a line using level_contour_px if stop equals 2 elbow must be firt pin inch + canvas_draw_line(canvas, level_contour_px, top_contour_px, level_contour_px, 63); + } else { + // Otherwise, draw a default line + canvas_draw_line(canvas, 0, top_contour_px, 0, 63); } - default: - // Handle other keys or do nothing - break; + + int slc_pin_px = (int)round( + (my_format.first_pin_inch + (my_model->pin_slc - 1) * my_format.pin_increment_inch) / + inches_per_px); + canvas_draw_icon(canvas, slc_pin_px - 2, top_contour_px - 25, &I_arrow_down); + + furi_string_printf(buffer, "%s", my_format.format_name); + canvas_draw_str(canvas, 100, 10, furi_string_get_cstr(buffer)); + furi_string_free(buffer); +} + +static bool key_copier_view_measure_input_callback(InputEvent* event, void* context) { + KeyCopierApp* app = (KeyCopierApp*)context; + if(event->type == InputTypeShort) { + switch(event->key) { + case InputKeyLeft: { + bool redraw = true; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + if(model->pin_slc > 1) { + model->pin_slc--; + } + }, + redraw); + break; + } + case InputKeyRight: { + bool redraw = true; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + if(model->pin_slc < model->format.pin_num) { + model->pin_slc++; + } + }, + redraw); + break; + } + case InputKeyUp: { + bool redraw = true; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + if(model->depth[model->pin_slc - 1] > model->format.min_depth_ind) { + if(model->pin_slc == 1) { // first pin only limited by the next one + if(model->depth[model->pin_slc] - model->depth[model->pin_slc - 1] < + model->format.macs) + model->depth[model->pin_slc - 1]--; + } else if(model->pin_slc == model->format.pin_num) { // last pin only limited by + // the previous one + if(model->depth[model->pin_slc - 2] - + model->depth[model->pin_slc - 1] < + model->format.macs) { + model->depth[model->pin_slc - 1]--; + } + } else { + if(model->depth[model->pin_slc] - model->depth[model->pin_slc - 1] < + model->format.macs && + model->depth[model->pin_slc - 2] - + model->depth[model->pin_slc - 1] < + model->format.macs) { + model->depth[model->pin_slc - 1]--; + } + } + } + }, + redraw); + break; + } + case InputKeyDown: { + bool redraw = true; + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + if(model->depth[model->pin_slc - 1] < model->format.max_depth_ind) { + if(model->pin_slc == 1) { // first pin only limited by the next one + if(model->depth[model->pin_slc - 1] - model->depth[model->pin_slc] < + model->format.macs) + model->depth[model->pin_slc - 1]++; + } else if(model->pin_slc == model->format.pin_num) { // last pin only limited by + // the previous one + if(model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc - 2] < + model->format.macs) { + model->depth[model->pin_slc - 1]++; + } + } else { + if(model->depth[model->pin_slc - 1] - model->depth[model->pin_slc] < + model->format.macs && + model->depth[model->pin_slc - 1] - + model->depth[model->pin_slc - 2] < + model->format.macs) { + model->depth[model->pin_slc - 1]++; + } + } + } + }, + redraw); + break; + } + default: + // Handle other keys or do nothing + break; + } } - } - return false; + return false; } -static KeyCopierApp *key_copier_app_alloc() { - KeyCopierApp *app = (KeyCopierApp *)malloc(sizeof(KeyCopierApp)); - - Gui *gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_attach_to_gui(app->view_dispatcher, gui, - ViewDispatcherTypeFullscreen); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - app->dialogs = furi_record_open(RECORD_DIALOGS); - app->file_path = furi_string_alloc(); - app->submenu = submenu_alloc(); - submenu_add_item(app->submenu, "Measure", KeyCopierSubmenuIndexMeasure, - key_copier_submenu_callback, app); - submenu_add_item(app->submenu, "Config", KeyCopierSubmenuIndexConfigure, - key_copier_submenu_callback, app); - submenu_add_item(app->submenu, "Save", KeyCopierSubmenuIndexSave, - key_copier_submenu_callback, app); - submenu_add_item(app->submenu, "Load", KeyCopierSubmenuIndexLoad, - key_copier_submenu_callback, app); - submenu_add_item(app->submenu, "About", KeyCopierSubmenuIndexAbout, - key_copier_submenu_callback, app); - view_set_previous_callback(submenu_get_view(app->submenu), - key_copier_navigation_exit_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSubmenu, - submenu_get_view(app->submenu)); - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); - - app->text_input = text_input_alloc(); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewTextInput, - text_input_get_view(app->text_input)); - app->temp_buffer_size = 32; - app->temp_buffer = (char *)malloc(app->temp_buffer_size); - app->temp_buffer = ""; - - app->view_measure = view_alloc(); - view_set_draw_callback(app->view_measure, - key_copier_view_measure_draw_callback); - view_set_input_callback(app->view_measure, - key_copier_view_measure_input_callback); - view_set_previous_callback(app->view_measure, - key_copier_navigation_submenu_callback); - view_set_context(app->view_measure, app); - view_allocate_model(app->view_measure, ViewModelTypeLockFree, - sizeof(KeyCopierModel)); - KeyCopierModel *model = view_get_model(app->view_measure); - - initialize_model(model); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewMeasure, - app->view_measure); - - app->variable_item_list_config = variable_item_list_alloc(); - app->view_config_e = view_alloc(); - view_set_context(app->view_config_e, app); - view_set_previous_callback(app->view_config_e, - key_copier_navigation_submenu_callback); - view_set_enter_callback(app->view_config_e, key_copier_config_enter_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_e, - app->view_config_e); - - View *view_buffer = view_alloc(); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, - view_buffer); - - app->view_save = view_alloc(); - view_set_context(app->view_save, app); - view_set_enter_callback(app->view_save, key_copier_view_save_callback); - view_set_previous_callback(app->view_save, - key_copier_navigation_submenu_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSave, - app->view_save); - - app->view_load = view_alloc(); - view_set_context(app->view_load, app); - view_set_enter_callback(app->view_load, key_copier_view_load_callback); - view_set_previous_callback(app->view_load, - key_copier_navigation_submenu_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewLoad, - app->view_load); - - app->widget_about = widget_alloc(); - widget_add_text_scroll_element( - app->widget_about, 0, 0, 128, 64, - "Key Maker App 1.0\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place " - "it on top of the screen.\n\n2. Use the contour to align your key.\n\n3. " - "Adjust each pin's depth until they match. It's easier if you look with " - "one eye closed.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial " - "thanks to Derek Jamison's Skeleton App Template."); - view_set_previous_callback(widget_get_view(app->widget_about), - key_copier_navigation_submenu_callback); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewAbout, - widget_get_view(app->widget_about)); - - app->notifications = furi_record_open(RECORD_NOTIFICATION); +static KeyCopierApp* key_copier_app_alloc() { + KeyCopierApp* app = (KeyCopierApp*)malloc(sizeof(KeyCopierApp)); + + Gui* gui = furi_record_open(RECORD_GUI); + + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + app->dialogs = furi_record_open(RECORD_DIALOGS); + app->file_path = furi_string_alloc(); + app->submenu = submenu_alloc(); + submenu_add_item( + app->submenu, "Measure", KeyCopierSubmenuIndexMeasure, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "Config", KeyCopierSubmenuIndexConfigure, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "Save", KeyCopierSubmenuIndexSave, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "Load", KeyCopierSubmenuIndexLoad, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "About", KeyCopierSubmenuIndexAbout, key_copier_submenu_callback, app); + view_set_previous_callback( + submenu_get_view(app->submenu), key_copier_navigation_exit_callback); + view_dispatcher_add_view( + app->view_dispatcher, KeyCopierViewSubmenu, submenu_get_view(app->submenu)); + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); + + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, KeyCopierViewTextInput, text_input_get_view(app->text_input)); + app->temp_buffer_size = 32; + app->temp_buffer = (char*)malloc(app->temp_buffer_size); + app->temp_buffer = ""; + + app->view_measure = view_alloc(); + view_set_draw_callback(app->view_measure, key_copier_view_measure_draw_callback); + view_set_input_callback(app->view_measure, key_copier_view_measure_input_callback); + view_set_previous_callback(app->view_measure, key_copier_navigation_submenu_callback); + view_set_context(app->view_measure, app); + view_allocate_model(app->view_measure, ViewModelTypeLockFree, sizeof(KeyCopierModel)); + KeyCopierModel* model = view_get_model(app->view_measure); + + initialize_model(model); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewMeasure, app->view_measure); + + app->variable_item_list_config = variable_item_list_alloc(); + app->view_config_e = view_alloc(); + view_set_context(app->view_config_e, app); + view_set_previous_callback(app->view_config_e, key_copier_navigation_submenu_callback); + view_set_enter_callback(app->view_config_e, key_copier_config_enter_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_e, app->view_config_e); + + View* view_buffer = view_alloc(); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewConfigure_i, view_buffer); + + app->view_save = view_alloc(); + view_set_context(app->view_save, app); + view_set_enter_callback(app->view_save, key_copier_view_save_callback); + view_set_previous_callback(app->view_save, key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSave, app->view_save); + + app->view_load = view_alloc(); + view_set_context(app->view_load, app); + view_set_enter_callback(app->view_load, key_copier_view_load_callback); + view_set_previous_callback(app->view_load, key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewLoad, app->view_load); + + app->widget_about = widget_alloc(); + widget_add_text_scroll_element( + app->widget_about, + 0, + 0, + 128, + 64, + "Key Maker App 1.0\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place " + "it on top of the screen.\n\n2. Use the contour to align your key.\n\n3. " + "Adjust each pin's depth until they match. It's easier if you look with " + "one eye closed.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial " + "thanks to Derek Jamison's Skeleton App Template."); + view_set_previous_callback( + widget_get_view(app->widget_about), key_copier_navigation_submenu_callback); + view_dispatcher_add_view( + app->view_dispatcher, KeyCopierViewAbout, widget_get_view(app->widget_about)); + + app->notifications = furi_record_open(RECORD_NOTIFICATION); #ifdef BACKLIGHT_ON - notification_message(app->notifications, - &sequence_display_backlight_enforce_on); + notification_message(app->notifications, &sequence_display_backlight_enforce_on); #endif - return app; + return app; } -static void key_copier_app_free(KeyCopierApp *app) { +static void key_copier_app_free(KeyCopierApp* app) { #ifdef BACKLIGHT_ON - notification_message(app->notifications, - &sequence_display_backlight_enforce_auto); + notification_message(app->notifications, &sequence_display_backlight_enforce_auto); #endif - furi_record_close(RECORD_NOTIFICATION); - - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewTextInput); - text_input_free(app->text_input); - free(app->temp_buffer); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewAbout); - widget_free(app->widget_about); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewMeasure); - with_view_model( - app->view_measure, KeyCopierModel * model, - { - if (model->depth != NULL) { - free(model->depth); - } - }, - false); - view_free(app->view_measure); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_e); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_i); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSave); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewLoad); - variable_item_list_free(app->variable_item_list_config); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSubmenu); - submenu_free(app->submenu); - view_dispatcher_free(app->view_dispatcher); - furi_record_close(RECORD_GUI); - - free(app); + furi_record_close(RECORD_NOTIFICATION); + + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewTextInput); + text_input_free(app->text_input); + free(app->temp_buffer); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewAbout); + widget_free(app->widget_about); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewMeasure); + with_view_model( + app->view_measure, + KeyCopierModel * model, + { + if(model->depth != NULL) { + free(model->depth); + } + }, + false); + view_free(app->view_measure); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_e); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_i); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSave); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewLoad); + variable_item_list_free(app->variable_item_list_config); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSubmenu); + submenu_free(app->submenu); + view_dispatcher_free(app->view_dispatcher); + furi_record_close(RECORD_GUI); + + free(app); } -int32_t main_key_copier_app(void *_p) { - UNUSED(_p); +int32_t main_key_copier_app(void* _p) { + UNUSED(_p); - KeyCopierApp *app = key_copier_app_alloc(); - view_dispatcher_run(app->view_dispatcher); + KeyCopierApp* app = key_copier_app_alloc(); + view_dispatcher_run(app->view_dispatcher); - key_copier_app_free(app); - return 0; + key_copier_app_free(app); + return 0; } From 71ef1f8991f744b6d5787d1a012bee33862e5476 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Thu, 16 Jan 2025 20:50:20 -0700 Subject: [PATCH 06/15] added various keys --- key_copier.c | 4 +- key_formats.c | 227 ++++++++++++++++++++++++++++++++++++++++++-------- key_formats.h | 40 ++++----- 3 files changed, 213 insertions(+), 58 deletions(-) diff --git a/key_copier.c b/key_copier.c index b40f06d..3c31707 100644 --- a/key_copier.c +++ b/key_copier.c @@ -534,9 +534,9 @@ static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { if(my_format.stop == 2) { // Draw a line using level_contour_px if stop equals 2 elbow must be firt pin inch canvas_draw_line(canvas, level_contour_px, top_contour_px, level_contour_px, 63); - } else { + // } else { // Otherwise, draw a default line - canvas_draw_line(canvas, 0, top_contour_px, 0, 63); + // canvas_draw_line(canvas, 0, top_contour_px, 0, 63); // too confusing but may want later } int slc_pin_px = (int)round( diff --git a/key_formats.c b/key_formats.c index edab249..98e3dc6 100644 --- a/key_formats.c +++ b/key_formats.c @@ -30,8 +30,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.031, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.335, .deepest_depth_inch = 0.2, @@ -43,35 +42,33 @@ const KeyFormat all_formats[] = { {.manufacturer = "Arrow", .format_name = "AR4", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C2", .first_pin_inch = 0.265, .last_pin_inch = 1.040, .pin_increment_inch = 0.155, .pin_num = 6, .pin_width_inch = 0.060, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will + .drill_angle = 90, // This should actually be 100 but the current resolution will // make 100 degrees very ugly and unsuable .uncut_depth_inch = 0.312, .deepest_depth_inch = 0.186, .depth_step_inch = 0.014, .min_depth_ind = 0, - .max_depth_ind = 10, + .max_depth_ind = 9, .macs = 6, .clearance = 8}, {.manufacturer = "Master Lock", .format_name = "M1", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C35", .first_pin_inch = 0.185, .last_pin_inch = 0.689, .pin_increment_inch = 0.126, .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.276, .deepest_depth_inch = 0.171, @@ -83,35 +80,33 @@ const KeyFormat all_formats[] = { {.manufacturer = "American", .format_name = "AM7", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C80", .first_pin_inch = 0.157, .last_pin_inch = 0.781, .pin_increment_inch = 0.125, .pin_num = 6, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.283, .deepest_depth_inch = 0.173, .depth_step_inch = 0.016, - .min_depth_ind = 0, + .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, .clearance = 8}, {.manufacturer = "Yale", .format_name = "Y2", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = ".025", .first_pin_inch = 0.200, .last_pin_inch = 1.025, .pin_increment_inch = 0.165, .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.320, .deepest_depth_inch = 0.145, @@ -123,80 +118,76 @@ const KeyFormat all_formats[] = { {.manufacturer = "Yale", .format_name = "Y11", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "CX55", .first_pin_inch = 0.124, .last_pin_inch = 0.502, .pin_increment_inch = 0.095, .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.246, .deepest_depth_inch = 0.167, .depth_step_inch = 0.020, - .min_depth_ind = 0, + .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, .clearance = 8}, {.manufacturer = "Sargent", .format_name = "S22", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C44", .first_pin_inch = 0.216, .last_pin_inch = 0.996, .pin_increment_inch = 0.156, .pin_num = 6, .pin_width_inch = 0.063, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.328, // double check .deepest_depth_inch = 0.148, .depth_step_inch = 0.020, - .min_depth_ind = 0, + .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, .clearance = 8}, {.manufacturer = "National", .format_name = "NA25", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C40", .first_pin_inch = 0.250, .last_pin_inch = 0.874, .pin_increment_inch = 0.156, .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.304, .deepest_depth_inch = 0.191, .depth_step_inch = 0.012, .min_depth_ind = 0, - .max_depth_ind = 10, + .max_depth_ind = 9, .macs = 7, .clearance = 8}, {.manufacturer = "Corbin", .format_name = "CO88", - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "C14", .first_pin_inch = 0.250, .last_pin_inch = 1.030, .pin_increment_inch = 0.156, .pin_num = 6, .pin_width_inch = 0.047, .elbow_inch = 0.1, - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.343, .deepest_depth_inch = 0.217, .depth_step_inch = 0.014, - .min_depth_ind = 0, + .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, .clearance = 8}, @@ -237,11 +228,47 @@ const KeyFormat all_formats[] = { .macs = 9, .clearance = 8}, + {.manufacturer = "National", + .format_name = "NA12", + .format_link = "C39", + .first_pin_inch = 0.150, + .last_pin_inch = 0.710, + .pin_increment_inch = 0.140, + .pin_num = 5, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, + .drill_angle = 90, + .uncut_depth_inch = 0.270, + .deepest_depth_inch = 0.157, + .depth_step_inch = 0.013, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 7, + .clearance = 8}, + + {.manufacturer = "Russwin", + .format_name = "RU45", + .format_link = "CX6", + .first_pin_inch = 0.250, + .last_pin_inch = 1.030, + .pin_increment_inch = 0.156, + .pin_num = 6, + .pin_width_inch = 0.053, + .elbow_inch = 0.1, + .drill_angle = 90, + .uncut_depth_inch = 0.343, + .deepest_depth_inch = 0.203, + .depth_step_inch = 0.028, + .min_depth_ind = 1, + .max_depth_ind = 6, + .macs = 5, + .clearance = 8}, + {.manufacturer = "Ford", .format_name = "H75", .sides = 2, .stop = 2, - .format_link = "https://lsamichigan.org/Tech/SCHLAGE_KeySpecs.pdf", + .format_link = "CX101", .first_pin_inch = 0.201, .last_pin_inch = 0.845, .pin_increment_inch = 0.092, @@ -249,13 +276,141 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.201, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = - 90, // This should actually be 100 but the current resolution will make + .drill_angle = 90, // This should actually be 100 but the current resolution will make // 100 degrees very ugly and unsuable .uncut_depth_inch = 0.354, .deepest_depth_inch = 0.254, .depth_step_inch = 0.025, - .min_depth_ind = 0, + .min_depth_ind = 1, .max_depth_ind = 5, .macs = 5, + .clearance = 0}, + + {.manufacturer = "Chevrolet", + .format_name = "B102", + .sides = 2, + .stop = 2, + .format_link = "", + .first_pin_inch = 0.205, + .last_pin_inch = 1.037, + .pin_increment_inch = 0.093, + .pin_num = 10, + .pin_width_inch = 0.039, + .elbow_inch = 0.205, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.315, + .deepest_depth_inch = 0.161, + .depth_step_inch = 0.026, + .min_depth_ind = 1, + .max_depth_ind = 4, + .macs = 5, + .clearance = 0}, + + {.manufacturer = "Dodge", + .format_name = "Y159", + .sides = 2, + .stop = 2, + .format_link = "CX102", + .first_pin_inch = 0.297, + .last_pin_inch = 0.941, + .pin_increment_inch = 0.092, + .pin_num = 8, + .pin_width_inch = 0.039, + .elbow_inch = 0.297, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.339, + .deepest_depth_inch = 0.197, + .depth_step_inch = 0.047, + .min_depth_ind = 1, + .max_depth_ind = 4, + .macs = 5, + .clearance = 0}, + + {.manufacturer = "Kawasaki", + .format_name = "KA14", + .sides = 2, + .format_link = "CMC50", + .first_pin_inch = 0.098, + .last_pin_inch = 0.591, + .pin_increment_inch = 0.098, + .pin_num = 6, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.258, + .deepest_depth_inch = 0.198, + .depth_step_inch = 0.020, + .min_depth_ind = 1, + .max_depth_ind = 4, + .macs = 4, + .clearance = 0}, + + {.manufacturer = "Yamaha", + .format_name = "YM63", + .sides = 2, + .format_link = "CMC71", + .first_pin_inch = 0.157, + .last_pin_inch = 0.748, + .pin_increment_inch = 0.098, + .pin_num = 7, + .pin_width_inch = 0.039, + .elbow_inch = 0.1, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.295, + .deepest_depth_inch = 0.236, + .depth_step_inch = 0.020, + .min_depth_ind = 1, + .max_depth_ind = 4, + .macs = 4, + .clearance = 0}, + + {.manufacturer = "Best (A2)", + .format_name = "SFIC", + .sides = 2, + .stop = 2, + .format_link = "C3", + .first_pin_inch = 0.081, + .last_pin_inch = 0.978, + .pin_increment_inch = 0.149, + .pin_num = 7, + .pin_width_inch = 0.051, + .elbow_inch = 0.081, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.318, + .deepest_depth_inch = 0.206, + .depth_step_inch = 0.025, + .min_depth_ind = 0, + .max_depth_ind = 9, + .macs = 5, + .clearance = 0}, + + {.manufacturer = "RV (FIC,GL,Bauer)", + .format_name = "RV", + .sides = 2, + .format_link = "Card", + .first_pin_inch = 0.126, + .last_pin_inch = 0.504, + .pin_increment_inch = 0.094, + .pin_num = 5, + .pin_width_inch = 0.039, + .elbow_inch = 0.126, // this should be equal to first pin inch for tip + // stopped key line + .drill_angle = 90, // This should actually be 100 but the current resolution will make + // 100 degrees very ugly and unsuable + .uncut_depth_inch = 0.260, + .deepest_depth_inch = 0.181, + .depth_step_inch = 0.040, + .min_depth_ind = 1, + .max_depth_ind = 3, + .macs = 3, .clearance = 0}}; diff --git a/key_formats.h b/key_formats.h index 20df3ca..67fb471 100644 --- a/key_formats.h +++ b/key_formats.h @@ -1,30 +1,30 @@ #ifndef KEY_FORMATS_H #define KEY_FORMATS_H -#define FORMAT_NUM 13 +#define FORMAT_NUM 21 typedef struct { - char *manufacturer; - char *format_name; - char *format_link; - int sides; - int stop; - double first_pin_inch; - double last_pin_inch; - double pin_increment_inch; - int pin_num; - double pin_width_inch; - double drill_angle; - double elbow_inch; + char* manufacturer; + char* format_name; + char* format_link; + int sides; + int stop; + double first_pin_inch; + double last_pin_inch; + double pin_increment_inch; + int pin_num; + double pin_width_inch; + double drill_angle; + double elbow_inch; - double uncut_depth_inch; - double deepest_depth_inch; - double depth_step_inch; - int min_depth_ind; - int max_depth_ind; + double uncut_depth_inch; + double deepest_depth_inch; + double depth_step_inch; + int min_depth_ind; + int max_depth_ind; - int macs; - int clearance; + int macs; + int clearance; } KeyFormat; extern const KeyFormat all_formats[FORMAT_NUM]; From 04ee4a8d05e79ae9d9c02e93a1174da5bbbeef69 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Thu, 16 Jan 2025 21:26:38 -0700 Subject: [PATCH 07/15] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1539f6b..d0bf3d6 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ A Flipper Zero app for measuring key bitting patterns. ## Instruction +*** +Download updated format.c, format.h, keycopier.c keycopier.h files +*** To measure your key: 1. Place it on top of the screen. 2. Use the contour to align your key. From ee2db574dab94e3c605c5e8c46f7f36df97a6d38 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:09:29 -0500 Subject: [PATCH 08/15] clearances updated --- key_formats.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/key_formats.c b/key_formats.c index 98e3dc6..80e75d4 100644 --- a/key_formats.c +++ b/key_formats.c @@ -76,7 +76,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 7, .macs = 7, - .clearance = 8}, + .clearance = 6}, {.manufacturer = "American", .format_name = "AM7", @@ -95,7 +95,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, - .clearance = 8}, + .clearance = 7}, {.manufacturer = "Yale", .format_name = "Y2", @@ -114,7 +114,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 9, - .clearance = 1}, + .clearance = 8}, {.manufacturer = "Yale", .format_name = "Y11", @@ -133,7 +133,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "Sargent", .format_name = "S22", @@ -152,7 +152,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, - .clearance = 8}, + .clearance = 7}, {.manufacturer = "National", .format_name = "NA25", @@ -262,7 +262,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 6, .macs = 5, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "Ford", .format_name = "H75", From 3899e09888f700c6f07ff835b6ad472fa1b20a1d Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Thu, 16 Jan 2025 22:27:00 -0700 Subject: [PATCH 09/15] Fixed SFIC --- key_formats.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/key_formats.c b/key_formats.c index 80e75d4..be1c027 100644 --- a/key_formats.c +++ b/key_formats.c @@ -76,7 +76,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 7, .macs = 7, - .clearance = 6}, + .clearance = 8}, {.manufacturer = "American", .format_name = "AM7", @@ -95,7 +95,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, - .clearance = 7}, + .clearance = 8}, {.manufacturer = "Yale", .format_name = "Y2", @@ -114,7 +114,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 9, - .clearance = 8}, + .clearance = 1}, {.manufacturer = "Yale", .format_name = "Y11", @@ -133,7 +133,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, - .clearance = 5}, + .clearance = 8}, {.manufacturer = "Sargent", .format_name = "S22", @@ -152,7 +152,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, - .clearance = 7}, + .clearance = 8}, {.manufacturer = "National", .format_name = "NA25", @@ -262,7 +262,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 6, .macs = 5, - .clearance = 5}, + .clearance = 8}, {.manufacturer = "Ford", .format_name = "H75", @@ -377,10 +377,10 @@ const KeyFormat all_formats[] = { .sides = 2, .stop = 2, .format_link = "C3", - .first_pin_inch = 0.081, - .last_pin_inch = 0.978, + .first_pin_inch = 0.170, + .last_pin_inch = 1.067, .pin_increment_inch = 0.149, - .pin_num = 7, + .pin_num = 6, .pin_width_inch = 0.051, .elbow_inch = 0.081, // this should be equal to first pin inch for tip // stopped key line From c88e1238d4220ae3a4fbbabceedf03a05612a127 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:35:23 -0500 Subject: [PATCH 10/15] More clerance fix and no bottom contour for double side --- key_copier.c | 17 +++++++++++++---- key_formats.c | 28 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/key_copier.c b/key_copier.c index 3c31707..60c6a0a 100644 --- a/key_copier.c +++ b/key_copier.c @@ -330,6 +330,8 @@ static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { int pre_extra_x_px = 0; int bottom_post_extra_x_px = 0; // new int bottom_pre_extra_x_px = 0; // new + int level_contour_px = + (int)round((my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); for(int current_pin = 1; current_pin <= my_model->format.pin_num; current_pin += 1) { double current_center_px = my_format.first_pin_inch + (current_pin - 1) * my_format.pin_increment_inch; @@ -461,6 +463,16 @@ static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { top_contour_px); // draw top shoulder last_depth = 0; pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); + if(my_format.sides == 2) { + canvas_draw_line( + canvas, + 0, + bottom_contour_px, + pin_center_px - pin_half_width_px - current_depth_px, + bottom_contour_px); // draw bottom shoulder (hidden by level contour) + } else { + canvas_draw_line(canvas, 0, 62, level_contour_px, 62); + } } if(current_pin == my_model->format.pin_num) { next_depth = 0; @@ -525,12 +537,9 @@ static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { } } - int level_contour_px = - (int)round((my_format.last_pin_inch + my_format.elbow_inch) / inches_per_px); int elbow_px = (int)round(my_format.elbow_inch / inches_per_px); - canvas_draw_line(canvas, 0, 62, level_contour_px, 62); canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + elbow_px, 62 - elbow_px); - + canvas_draw_line(canvas, 0, top_contour_px - 6, 0, top_contour_px); if(my_format.stop == 2) { // Draw a line using level_contour_px if stop equals 2 elbow must be firt pin inch canvas_draw_line(canvas, level_contour_px, top_contour_px, level_contour_px, 63); diff --git a/key_formats.c b/key_formats.c index be1c027..4accccc 100644 --- a/key_formats.c +++ b/key_formats.c @@ -57,7 +57,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 6, - .clearance = 8}, + .clearance = 7}, {.manufacturer = "Master Lock", .format_name = "M1", @@ -95,7 +95,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "Yale", .format_name = "Y2", @@ -113,8 +113,8 @@ const KeyFormat all_formats[] = { .depth_step_inch = 0.025, .min_depth_ind = 0, .max_depth_ind = 9, - .macs = 9, - .clearance = 1}, + .macs = 5, + .clearance = 4}, {.manufacturer = "Yale", .format_name = "Y11", @@ -133,7 +133,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, - .clearance = 8}, + .clearance = 3}, {.manufacturer = "Sargent", .format_name = "S22", @@ -152,7 +152,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "National", .format_name = "NA25", @@ -262,7 +262,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 6, .macs = 5, - .clearance = 8}, + .clearance = 3}, {.manufacturer = "Ford", .format_name = "H75", @@ -284,7 +284,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 5, - .clearance = 0}, + .clearance = 2}, {.manufacturer = "Chevrolet", .format_name = "B102", @@ -306,7 +306,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 0}, + .clearance = 2}, {.manufacturer = "Dodge", .format_name = "Y159", @@ -328,7 +328,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 0}, + .clearance = 1}, {.manufacturer = "Kawasaki", .format_name = "KA14", @@ -349,7 +349,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "Yamaha", .format_name = "YM63", @@ -370,7 +370,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "Best (A2)", .format_name = "SFIC", @@ -392,7 +392,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 5, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "RV (FIC,GL,Bauer)", .format_name = "RV", @@ -413,4 +413,4 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 3, .macs = 3, - .clearance = 0}}; + .clearance = 1}}; From f5176d76ab8716fdc8c462171f4f20853e92b0a6 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:40:36 -0500 Subject: [PATCH 11/15] One more clearance fix --- key_formats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/key_formats.c b/key_formats.c index 4accccc..c0318f9 100644 --- a/key_formats.c +++ b/key_formats.c @@ -76,7 +76,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 7, .macs = 7, - .clearance = 8}, + .clearance = 6}, {.manufacturer = "American", .format_name = "AM7", From 6f28815585abc0c8fb4ec43c11fd9630eb118944 Mon Sep 17 00:00:00 2001 From: HonestLocksmith Date: Thu, 16 Jan 2025 22:49:20 -0700 Subject: [PATCH 12/15] Fixed y2 clearance --- key_formats.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/key_formats.c b/key_formats.c index c0318f9..37d8933 100644 --- a/key_formats.c +++ b/key_formats.c @@ -57,7 +57,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 6, - .clearance = 7}, + .clearance = 8}, {.manufacturer = "Master Lock", .format_name = "M1", @@ -76,7 +76,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 7, .macs = 7, - .clearance = 6}, + .clearance = 8}, {.manufacturer = "American", .format_name = "AM7", @@ -95,14 +95,14 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, - .clearance = 5}, + .clearance = 8}, {.manufacturer = "Yale", .format_name = "Y2", .format_link = ".025", - .first_pin_inch = 0.200, - .last_pin_inch = 1.025, - .pin_increment_inch = 0.165, + .first_pin_inch = 0.250, + .last_pin_inch = 1.095, + .pin_increment_inch = 0.185, .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, @@ -113,8 +113,8 @@ const KeyFormat all_formats[] = { .depth_step_inch = 0.025, .min_depth_ind = 0, .max_depth_ind = 9, - .macs = 5, - .clearance = 4}, + .macs = 9, + .clearance = 1}, {.manufacturer = "Yale", .format_name = "Y11", @@ -133,7 +133,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, - .clearance = 3}, + .clearance = 8}, {.manufacturer = "Sargent", .format_name = "S22", @@ -152,7 +152,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, - .clearance = 5}, + .clearance = 8}, {.manufacturer = "National", .format_name = "NA25", @@ -262,7 +262,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 6, .macs = 5, - .clearance = 3}, + .clearance = 8}, {.manufacturer = "Ford", .format_name = "H75", @@ -284,7 +284,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 5, - .clearance = 2}, + .clearance = 0}, {.manufacturer = "Chevrolet", .format_name = "B102", @@ -306,7 +306,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 2}, + .clearance = 0}, {.manufacturer = "Dodge", .format_name = "Y159", @@ -328,7 +328,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 1}, + .clearance = 0}, {.manufacturer = "Kawasaki", .format_name = "KA14", @@ -349,7 +349,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 3}, + .clearance = 0}, {.manufacturer = "Yamaha", .format_name = "YM63", @@ -370,7 +370,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 3}, + .clearance = 0}, {.manufacturer = "Best (A2)", .format_name = "SFIC", @@ -392,7 +392,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 5, - .clearance = 3}, + .clearance = 0}, {.manufacturer = "RV (FIC,GL,Bauer)", .format_name = "RV", @@ -413,4 +413,4 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 3, .macs = 3, - .clearance = 1}}; + .clearance = 0}}; From b4b14f5c5f7130aa5f42e81dce06e3e08d0b833c Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:54:43 -0500 Subject: [PATCH 13/15] Revert "Fixed y2 clearance" This reverts commit 6f28815585abc0c8fb4ec43c11fd9630eb118944. --- key_formats.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/key_formats.c b/key_formats.c index 37d8933..c0318f9 100644 --- a/key_formats.c +++ b/key_formats.c @@ -57,7 +57,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 6, - .clearance = 8}, + .clearance = 7}, {.manufacturer = "Master Lock", .format_name = "M1", @@ -76,7 +76,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 7, .macs = 7, - .clearance = 8}, + .clearance = 6}, {.manufacturer = "American", .format_name = "AM7", @@ -95,14 +95,14 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 8, .macs = 7, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "Yale", .format_name = "Y2", .format_link = ".025", - .first_pin_inch = 0.250, - .last_pin_inch = 1.095, - .pin_increment_inch = 0.185, + .first_pin_inch = 0.200, + .last_pin_inch = 1.025, + .pin_increment_inch = 0.165, .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, @@ -113,8 +113,8 @@ const KeyFormat all_formats[] = { .depth_step_inch = 0.025, .min_depth_ind = 0, .max_depth_ind = 9, - .macs = 9, - .clearance = 1}, + .macs = 5, + .clearance = 4}, {.manufacturer = "Yale", .format_name = "Y11", @@ -133,7 +133,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 7, - .clearance = 8}, + .clearance = 3}, {.manufacturer = "Sargent", .format_name = "S22", @@ -152,7 +152,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 10, .macs = 7, - .clearance = 8}, + .clearance = 5}, {.manufacturer = "National", .format_name = "NA25", @@ -262,7 +262,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 6, .macs = 5, - .clearance = 8}, + .clearance = 3}, {.manufacturer = "Ford", .format_name = "H75", @@ -284,7 +284,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 5, .macs = 5, - .clearance = 0}, + .clearance = 2}, {.manufacturer = "Chevrolet", .format_name = "B102", @@ -306,7 +306,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 0}, + .clearance = 2}, {.manufacturer = "Dodge", .format_name = "Y159", @@ -328,7 +328,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 5, - .clearance = 0}, + .clearance = 1}, {.manufacturer = "Kawasaki", .format_name = "KA14", @@ -349,7 +349,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "Yamaha", .format_name = "YM63", @@ -370,7 +370,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 4, .macs = 4, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "Best (A2)", .format_name = "SFIC", @@ -392,7 +392,7 @@ const KeyFormat all_formats[] = { .min_depth_ind = 0, .max_depth_ind = 9, .macs = 5, - .clearance = 0}, + .clearance = 3}, {.manufacturer = "RV (FIC,GL,Bauer)", .format_name = "RV", @@ -413,4 +413,4 @@ const KeyFormat all_formats[] = { .min_depth_ind = 1, .max_depth_ind = 3, .macs = 3, - .clearance = 0}}; + .clearance = 1}}; From fd30c738518c74a97a0f55a83064ad3d5987a02a Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 01:00:13 -0500 Subject: [PATCH 14/15] formats and Y2 macs untouched --- key_formats.c | 54 ++++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/key_formats.c b/key_formats.c index c0318f9..332abde 100644 --- a/key_formats.c +++ b/key_formats.c @@ -4,7 +4,6 @@ const KeyFormat all_formats[] = { {.manufacturer = "Kwikset", .format_name = "KW1", - .format_link = "https://lsamichigan.org/Tech/Kwikset_KeySpecs.pdf", .first_pin_inch = 0.247, .last_pin_inch = 0.847, @@ -49,8 +48,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.060, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will - // make 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.312, .deepest_depth_inch = 0.186, .depth_step_inch = 0.014, @@ -68,8 +66,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.276, .deepest_depth_inch = 0.171, .depth_step_inch = 0.015, @@ -87,8 +84,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.283, .deepest_depth_inch = 0.173, .depth_step_inch = 0.016, @@ -100,20 +96,19 @@ const KeyFormat all_formats[] = { {.manufacturer = "Yale", .format_name = "Y2", .format_link = ".025", - .first_pin_inch = 0.200, - .last_pin_inch = 1.025, - .pin_increment_inch = 0.165, + .first_pin_inch = 0.250, + .last_pin_inch = 1.095, + .pin_increment_inch = 0.185, .pin_num = 6, .pin_width_inch = 0.054, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.320, .deepest_depth_inch = 0.145, .depth_step_inch = 0.025, .min_depth_ind = 0, .max_depth_ind = 9, - .macs = 5, + .macs = 9, .clearance = 4}, {.manufacturer = "Yale", @@ -125,8 +120,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.246, .deepest_depth_inch = 0.167, .depth_step_inch = 0.020, @@ -144,8 +138,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.063, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.328, // double check .deepest_depth_inch = 0.148, .depth_step_inch = 0.020, @@ -163,8 +156,7 @@ const KeyFormat all_formats[] = { .pin_num = 5, .pin_width_inch = 0.039, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.304, .deepest_depth_inch = 0.191, .depth_step_inch = 0.012, @@ -182,8 +174,7 @@ const KeyFormat all_formats[] = { .pin_num = 6, .pin_width_inch = 0.047, .elbow_inch = 0.1, - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.343, .deepest_depth_inch = 0.217, .depth_step_inch = 0.014, @@ -276,8 +267,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.201, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.354, .deepest_depth_inch = 0.254, .depth_step_inch = 0.025, @@ -298,8 +288,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.205, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.315, .deepest_depth_inch = 0.161, .depth_step_inch = 0.026, @@ -320,8 +309,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.297, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.339, .deepest_depth_inch = 0.197, .depth_step_inch = 0.047, @@ -341,8 +329,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.1, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.258, .deepest_depth_inch = 0.198, .depth_step_inch = 0.020, @@ -362,8 +349,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.1, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.295, .deepest_depth_inch = 0.236, .depth_step_inch = 0.020, @@ -384,8 +370,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.051, .elbow_inch = 0.081, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.318, .deepest_depth_inch = 0.206, .depth_step_inch = 0.025, @@ -405,8 +390,7 @@ const KeyFormat all_formats[] = { .pin_width_inch = 0.039, .elbow_inch = 0.126, // this should be equal to first pin inch for tip // stopped key line - .drill_angle = 90, // This should actually be 100 but the current resolution will make - // 100 degrees very ugly and unsuable + .drill_angle = 90, .uncut_depth_inch = 0.260, .deepest_depth_inch = 0.181, .depth_step_inch = 0.040, From f4829abe51c96428d5c5f46406a0d19a3f12931a Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 17 Jan 2025 01:07:11 -0500 Subject: [PATCH 15/15] Update README and in-app About page --- README.md | 5 ++--- key_copier.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d0bf3d6..adc5d63 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,6 @@ A Flipper Zero app for measuring key bitting patterns. ## Instruction -*** -Download updated format.c, format.h, keycopier.c keycopier.h files -*** To measure your key: 1. Place it on top of the screen. 2. Use the contour to align your key. @@ -12,7 +9,9 @@ To measure your key: ## Special Thanks - Thank [@jamisonderek](https://github.com/jamisonderek) for his [Flipper Zero Tutorial repository](https://github.com/jamisonderek/flipper-zero-tutorials) and [YouTube channel](https://github.com/jamisonderek/flipper-zero-tutorials#:~:text=YouTube%3A%20%40MrDerekJamison)! This app is built with his Skeleton App and GPIO Wiegand app as references. +- Thank [@HonestLocksmith](https://github.com/HonestLocksmith) for PR #13 and #20. TONS of new key formats and supports for DOUBLE-SIDED keys are added. We have car keys now! - [Project channel](https://discord.com/channels/1112390971250974782/1264067969634402356) + diff --git a/key_copier.c b/key_copier.c index 60c6a0a..5900248 100644 --- a/key_copier.c +++ b/key_copier.c @@ -735,7 +735,7 @@ static KeyCopierApp* key_copier_app_alloc() { 0, 128, 64, - "Key Maker App 1.0\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place " + "Key Maker App 1.1\nAuthor: @Torron\n\nTo measure your key:\n\n1. Place " "it on top of the screen.\n\n2. Use the contour to align your key.\n\n3. " "Adjust each pin's depth until they match. It's easier if you look with " "one eye closed.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial "