| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #include "../mag_i.h"
- #include "../mag_state.h"
- #include "../helpers/mag_helpers.h"
- #define TAG "MagSceneEmulateConfig"
- enum VarItemListIndex {
- VarItemListIndexPinInput,
- VarItemListIndexPinOutput,
- VarItemListIndexPinEnable,
- VarItemListIndexNRepeats,
- VarItemListIndexRepeatModeOn,
- VarItemListIndexAllowUART,
- };
- static const char* gpio[] = {
- [MagPinA7] = "2 (A7)",
- [MagPinA6] = "3 (A6)",
- [MagPinA4] = "4 (A4)",
- [MagPinB3] = "5 (B3)",
- [MagPinB2] = "6 (B2)",
- [MagPinC3] = "7 (C3)",
- [MagPinC1] = "15 (C1)",
- [MagPinC0] = "16 (C0)",
- };
- const uint8_t GPIO_COUNT = COUNT_OF(gpio);
- // static const char* uart_pins[] = {[DapUartTypeUSART1] = "13,14", [DapUartTypeLPUART1] = "15,16"};
- // static const char* uart_swap[] = {[DapUartTXRXNormal] = "No", [DapUartTXRXSwap] = "Yes"};
- #define N_REPEATS_COUNT 10
- const char* const n_repeats_text[N_REPEATS_COUNT] = {
- "2",
- "3",
- "4",
- "5",
- "6",
- "7",
- "8",
- "9",
- "10",
- "20",
- };
- const uint32_t n_repeats_value[N_REPEATS_COUNT] = {
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 20,
- };
- #define OFF_ON_COUNT 2
- const char* const off_on_text[OFF_ON_COUNT] = {
- "OFF",
- "ON",
- };
- void mag_scene_settings_var_item_list_callback(void* context, uint32_t index) {
- Mag* mag = context;
- view_dispatcher_send_custom_event(mag->view_dispatcher, index);
- }
- static void mag_scene_settings_set_gpio(VariableItem* item, MagPin* pin_out) {
- MagPin pin = variable_item_get_current_value_index(item);
- variable_item_set_current_value_text(item, gpio[pin]);
- *pin_out = pin;
- }
- static void mag_scene_settings_set_gpio_input(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- mag_scene_settings_set_gpio(item, &mag->state.pin_input);
- }
- static void mag_scene_settings_set_gpio_output(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- mag_scene_settings_set_gpio(item, &mag->state.pin_output);
- }
- static void mag_scene_settings_set_gpio_enable(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- mag_scene_settings_set_gpio(item, &mag->state.pin_enable);
- }
- static void mag_scene_settings_set_n_repeats(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- uint8_t index = variable_item_get_current_value_index(item);
- variable_item_set_current_value_text(item, n_repeats_text[index]);
- mag->state.n_repeats = n_repeats_value[index];
- }
- static void mag_scene_settings_set_bool(VariableItem* item, bool* bool_out) {
- uint8_t index = variable_item_get_current_value_index(item);
- variable_item_set_current_value_text(item, off_on_text[index]);
- *bool_out = (bool)index;
- }
- static void mag_scene_settings_set_repeat_mode(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- mag_scene_settings_set_bool(item, &mag->state.repeat_mode);
- }
- static void mag_scene_settings_set_allow_uart(VariableItem* item) {
- Mag* mag = variable_item_get_context(item);
- // rising change when value index is truth-y, and prior value false
- bool rising = !mag->state.allow_uart && !!variable_item_get_current_value_index(item);
- // trigger dialog only on rising change
- if(rising) {
- scene_manager_set_scene_state(mag->scene_manager, MagSceneSettings, (uint32_t)item);
- view_dispatcher_send_custom_event(mag->view_dispatcher, MagEventConfirmDialog);
- }
- // set value & text based on current varitem index
- mag_scene_settings_set_bool(item, &mag->state.allow_uart);
- }
- static void mag_pin_variable_item_list_add(
- Mag* mag,
- const char* label,
- MagPin pin,
- VariableItemChangeCallback change_callback) {
- VariableItem* item =
- variable_item_list_add(mag->variable_item_list, label, GPIO_COUNT, change_callback, mag);
- variable_item_set_current_value_index(item, pin);
- variable_item_set_current_value_text(item, gpio[pin]);
- }
- static void mag_bool_variable_item_list_add(
- Mag* mag,
- const char* label,
- bool value,
- VariableItemChangeCallback change_callback) {
- VariableItem* item =
- variable_item_list_add(mag->variable_item_list, label, OFF_ON_COUNT, change_callback, mag);
- uint32_t value_index = (uint32_t)value;
- variable_item_set_current_value_index(item, value_index);
- variable_item_set_current_value_text(item, off_on_text[value_index]);
- }
- void mag_scene_settings_on_enter(void* context) {
- Mag* mag = context;
- VariableItemList* var_item_list = mag->variable_item_list;
- VariableItem* item;
- uint32_t value_index;
- // reload state in the event temporary changes have been
- // made on the emulate config screen
- // only changes made in this scene should be saved, and this scene
- // should always represent the saved settings, not the transient ones for
- // a given emulation.
- mag_state_load(&mag->state);
- mag_pin_variable_item_list_add(
- mag, "Input pin:", mag->state.pin_input, mag_scene_settings_set_gpio_input);
- mag_pin_variable_item_list_add(
- mag, "Output pin:", mag->state.pin_output, mag_scene_settings_set_gpio_output);
- mag_pin_variable_item_list_add(
- mag, "Enable pin:", mag->state.pin_enable, mag_scene_settings_set_gpio_enable);
- mag_bool_variable_item_list_add(
- mag, "Repeat default:", mag->state.repeat_mode, mag_scene_settings_set_repeat_mode);
- item = variable_item_list_add(
- var_item_list, "# repeats: ", N_REPEATS_COUNT, mag_scene_settings_set_n_repeats, mag);
- value_index = value_index_uint32(mag->state.n_repeats, n_repeats_value, N_REPEATS_COUNT);
- variable_item_set_current_value_index(item, value_index);
- variable_item_set_current_value_text(item, n_repeats_text[value_index]);
- mag_bool_variable_item_list_add(
- mag, "UART MSR:", mag->state.allow_uart, mag_scene_settings_set_allow_uart);
- variable_item_list_set_enter_callback(
- var_item_list, mag_scene_settings_var_item_list_callback, mag);
- variable_item_list_set_selected_item(
- var_item_list, scene_manager_get_scene_state(mag->scene_manager, MagSceneSettings));
- view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewVariableItemList);
- }
- void mag_scene_settings_dialog_invalid_pins(Mag* mag) {
- SceneManager* scene_manager = mag->scene_manager;
- DialogMessage* message = dialog_message_alloc();
- dialog_message_set_header(message, "Invalid Pin Config!", 64, 0, AlignCenter, AlignTop);
- dialog_message_set_buttons(message, "Modify", NULL, "Reset");
- dialog_message_set_text(
- message,
- "Pins cannot overlap.\nChange, or reset to defaults.",
- 64,
- 32,
- AlignCenter,
- AlignCenter);
- DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), message);
- dialog_message_free(message);
- furi_record_close(RECORD_DIALOGS);
- if(res == DialogMessageButtonRight) {
- mag_state_gpio_reset(&mag->state);
- scene_manager_previous_scene(scene_manager);
- }
- }
- bool mag_scene_settings_on_event(void* context, SceneManagerEvent event) {
- Mag* mag = context;
- SceneManager* scene_manager = mag->scene_manager;
- bool consumed = false;
- switch(event.type) {
- case SceneManagerEventTypeBack:
- // when attempting to exit, validate pin configuration
- // if invalid, prompt
- consumed = true;
- if(!mag_state_gpio_is_valid(&mag->state)) {
- mag_scene_settings_dialog_invalid_pins(mag);
- } else {
- scene_manager_previous_scene(scene_manager);
- }
- break;
- case SceneManagerEventTypeCustom:
- // scene_manager_set_scene_state(mag->scene_manager, MagSceneSettings, event.event);
- consumed = true;
- if(event.event == MagEventConfirmDialog) {
- DialogMessage* msg = dialog_message_alloc();
- dialog_message_set_header(msg, "UART MSR", 64, 0, AlignCenter, AlignTop);
- dialog_message_set_buttons(msg, "No", NULL, "Yes");
- dialog_message_set_text(
- msg,
- "This option requires a\nUART-compatible mag reader.\nIs it installed?\n",
- 64,
- 32,
- AlignCenter,
- AlignCenter);
- DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), msg);
- if(res != DialogMessageButtonRight) {
- // if not "Yes", reset to "OFF" (0 / false-y)
- VariableItem* item =
- (VariableItem*)scene_manager_get_scene_state(scene_manager, MagSceneSettings);
- variable_item_set_current_value_index(item, 0);
- mag_scene_settings_set_bool(item, &mag->state.allow_uart);
- }
- dialog_message_free(msg);
- furi_record_close(RECORD_DIALOGS);
- // clear item from scene state
- scene_manager_set_scene_state(scene_manager, MagSceneSettings, 0);
- }
- break;
- default:
- break;
- }
- return consumed;
- }
- void mag_scene_settings_on_exit(void* context) {
- Mag* mag = context;
- variable_item_list_reset(mag->variable_item_list);
- mag_state_save(&mag->state);
- }
|