mag_scene_settings.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "../mag_i.h"
  2. #include "../mag_state.h"
  3. #include "../helpers/mag_helpers.h"
  4. #define TAG "MagSceneEmulateConfig"
  5. enum VarItemListIndex {
  6. VarItemListIndexPinInput,
  7. VarItemListIndexPinOutput,
  8. VarItemListIndexPinEnable,
  9. VarItemListIndexNRepeats,
  10. VarItemListIndexRepeatModeOn,
  11. #ifndef FW_ORIGIN_Official
  12. VarItemListIndexAllowUART,
  13. #endif
  14. };
  15. static const char* gpio[] = {
  16. [MagPinA7] = "2 (A7)",
  17. [MagPinA6] = "3 (A6)",
  18. [MagPinA4] = "4 (A4)",
  19. [MagPinB3] = "5 (B3)",
  20. [MagPinB2] = "6 (B2)",
  21. [MagPinC3] = "7 (C3)",
  22. [MagPinC1] = "15 (C1)",
  23. [MagPinC0] = "16 (C0)",
  24. };
  25. const uint8_t GPIO_COUNT = COUNT_OF(gpio);
  26. // static const char* uart_pins[] = {[DapUartTypeUSART1] = "13,14", [DapUartTypeLPUART1] = "15,16"};
  27. // static const char* uart_swap[] = {[DapUartTXRXNormal] = "No", [DapUartTXRXSwap] = "Yes"};
  28. #define N_REPEATS_COUNT 10
  29. const char* const n_repeats_text[N_REPEATS_COUNT] = {
  30. "2",
  31. "3",
  32. "4",
  33. "5",
  34. "6",
  35. "7",
  36. "8",
  37. "9",
  38. "10",
  39. "20",
  40. };
  41. const uint32_t n_repeats_value[N_REPEATS_COUNT] = {
  42. 2,
  43. 3,
  44. 4,
  45. 5,
  46. 6,
  47. 7,
  48. 8,
  49. 9,
  50. 10,
  51. 20,
  52. };
  53. #define OFF_ON_COUNT 2
  54. const char* const off_on_text[OFF_ON_COUNT] = {
  55. "OFF",
  56. "ON",
  57. };
  58. void mag_scene_settings_var_item_list_callback(void* context, uint32_t index) {
  59. Mag* mag = context;
  60. view_dispatcher_send_custom_event(mag->view_dispatcher, index);
  61. }
  62. static void mag_scene_settings_set_gpio(VariableItem* item, MagPin* pin_out) {
  63. MagPin pin = variable_item_get_current_value_index(item);
  64. variable_item_set_current_value_text(item, gpio[pin]);
  65. *pin_out = pin;
  66. }
  67. static void mag_scene_settings_set_gpio_input(VariableItem* item) {
  68. Mag* mag = variable_item_get_context(item);
  69. mag_scene_settings_set_gpio(item, &mag->state.pin_input);
  70. };
  71. static void mag_scene_settings_set_gpio_output(VariableItem* item) {
  72. Mag* mag = variable_item_get_context(item);
  73. mag_scene_settings_set_gpio(item, &mag->state.pin_output);
  74. };
  75. static void mag_scene_settings_set_gpio_enable(VariableItem* item) {
  76. Mag* mag = variable_item_get_context(item);
  77. mag_scene_settings_set_gpio(item, &mag->state.pin_enable);
  78. };
  79. static void mag_scene_settings_set_n_repeats(VariableItem* item) {
  80. Mag* mag = variable_item_get_context(item);
  81. uint8_t index = variable_item_get_current_value_index(item);
  82. variable_item_set_current_value_text(item, n_repeats_text[index]);
  83. mag->state.n_repeats = n_repeats_value[index];
  84. }
  85. static void mag_scene_settings_set_bool(VariableItem* item, bool* bool_out) {
  86. uint8_t index = variable_item_get_current_value_index(item);
  87. variable_item_set_current_value_text(item, off_on_text[index]);
  88. *bool_out = (bool)index;
  89. }
  90. static void mag_scene_settings_set_repeat_mode(VariableItem* item) {
  91. Mag* mag = variable_item_get_context(item);
  92. mag_scene_settings_set_bool(item, &mag->state.repeat_mode);
  93. }
  94. /*
  95. static void mag_scene_settings_set_allow_uart(VariableItem* item) {
  96. Mag* mag = variable_item_get_context(item);
  97. bool rising = !(mag->state.allow_uart);
  98. // trigger dialog only on rising change
  99. if(rising) {
  100. DialogMessage* msg = dialog_message_alloc();
  101. dialog_message_set_header(msg, "UART MSR", 64, 0, AlignCenter, AlignTop);
  102. dialog_message_set_buttons(msg, "No", NULL, "Yes");
  103. dialog_message_set_text(
  104. msg,
  105. "This option requires a\nUART-compatible mag reader.\nIs it installed?\n",
  106. 64,
  107. 32,
  108. AlignCenter,
  109. AlignCenter);
  110. DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), msg);
  111. if(res != DialogMessageButtonRight) {
  112. // if not "Yes", reset index
  113. variable_item_set_current_value_index(item, (uint32_t)mag->state.allow_uart);
  114. }
  115. dialog_message_free(msg);
  116. furi_record_close(RECORD_DIALOGS);
  117. }
  118. // set value & text based on current varitem index
  119. mag_scene_settings_set_bool(item, &mag->state.allow_uart);
  120. }
  121. */
  122. static void mag_pin_variable_item_list_add(
  123. Mag* mag,
  124. const char* label,
  125. MagPin pin,
  126. VariableItemChangeCallback change_callback) {
  127. VariableItem* item =
  128. variable_item_list_add(mag->variable_item_list, label, GPIO_COUNT, change_callback, mag);
  129. variable_item_set_current_value_index(item, pin);
  130. variable_item_set_current_value_text(item, gpio[pin]);
  131. }
  132. static void mag_bool_variable_item_list_add(
  133. Mag* mag,
  134. const char* label,
  135. bool value,
  136. VariableItemChangeCallback change_callback) {
  137. VariableItem* item =
  138. variable_item_list_add(mag->variable_item_list, label, OFF_ON_COUNT, change_callback, mag);
  139. uint32_t value_index = (uint32_t)value;
  140. variable_item_set_current_value_index(item, value_index);
  141. variable_item_set_current_value_text(item, off_on_text[value_index]);
  142. }
  143. void mag_scene_settings_on_enter(void* context) {
  144. Mag* mag = context;
  145. VariableItemList* var_item_list = mag->variable_item_list;
  146. VariableItem* item;
  147. uint32_t value_index;
  148. // reload state in the event temporary changes have been
  149. // made on the emulate config screen
  150. // only changes made in this scene should be saved, and this scene
  151. // should always represent the saved settings, not the transient ones for
  152. // a given emulation.
  153. mag_state_load(&mag->state);
  154. mag_pin_variable_item_list_add(
  155. mag, "Input pin:", mag->state.pin_input, mag_scene_settings_set_gpio_input);
  156. mag_pin_variable_item_list_add(
  157. mag, "Output pin:", mag->state.pin_output, mag_scene_settings_set_gpio_output);
  158. mag_pin_variable_item_list_add(
  159. mag, "Enable pin:", mag->state.pin_enable, mag_scene_settings_set_gpio_enable);
  160. mag_bool_variable_item_list_add(
  161. mag, "Repeat default:", mag->state.repeat_mode, mag_scene_settings_set_repeat_mode);
  162. item = variable_item_list_add(
  163. var_item_list, "# repeats: ", N_REPEATS_COUNT, mag_scene_settings_set_n_repeats, mag);
  164. value_index = value_index_uint32(mag->state.n_repeats, n_repeats_value, N_REPEATS_COUNT);
  165. variable_item_set_current_value_index(item, value_index);
  166. variable_item_set_current_value_text(item, n_repeats_text[value_index]);
  167. #ifndef FW_ORIGIN_Official
  168. item = variable_item_list_add(var_item_list, "UART MSR: ", 1, NULL, mag);
  169. variable_item_set_current_value_text(item, mag->state.allow_uart ? "ON" : "OFF");
  170. #endif
  171. //mag_bool_variable_item_list_add(
  172. // mag, "UART MSR:", mag->state.allow_uart, mag_scene_settings_set_allow_uart);
  173. variable_item_list_set_enter_callback(
  174. var_item_list, mag_scene_settings_var_item_list_callback, mag);
  175. variable_item_list_set_selected_item(
  176. var_item_list, scene_manager_get_scene_state(mag->scene_manager, MagSceneSettings));
  177. view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewVariableItemList);
  178. }
  179. void mag_scene_settings_dialog_invalid_pins(Mag* mag) {
  180. SceneManager* scene_manager = mag->scene_manager;
  181. DialogMessage* message = dialog_message_alloc();
  182. dialog_message_set_header(message, "Invalid Pin Config!", 64, 0, AlignCenter, AlignTop);
  183. dialog_message_set_buttons(message, "Modify", NULL, "Reset");
  184. dialog_message_set_text(
  185. message,
  186. "Pins cannot overlap.\nChange, or reset to defaults.",
  187. 64,
  188. 32,
  189. AlignCenter,
  190. AlignCenter);
  191. DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), message);
  192. dialog_message_free(message);
  193. furi_record_close(RECORD_DIALOGS);
  194. if(res == DialogMessageButtonRight) {
  195. mag_state_gpio_reset(&mag->state);
  196. scene_manager_previous_scene(scene_manager);
  197. }
  198. }
  199. #ifndef FW_ORIGIN_Official
  200. void mag_scene_settings_dialog_allow_uart(Mag* mag) {
  201. bool change = mag->state.allow_uart;
  202. if(!change) {
  203. DialogMessage* msg = dialog_message_alloc();
  204. dialog_message_set_header(msg, "UART MSR", 64, 0, AlignCenter, AlignTop);
  205. dialog_message_set_buttons(msg, "No", NULL, "Yes");
  206. dialog_message_set_text(
  207. msg,
  208. "This option requires a\nUART-compatible mag reader.\nIs it installed?\n",
  209. 64,
  210. 32,
  211. AlignCenter,
  212. AlignCenter);
  213. DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), msg);
  214. if(res == DialogMessageButtonRight) {
  215. change = true;
  216. }
  217. dialog_message_free(msg);
  218. furi_record_close(RECORD_DIALOGS);
  219. }
  220. if(change) {
  221. mag->state.allow_uart = !mag->state.allow_uart;
  222. variable_item_set_current_value_text(
  223. variable_item_list_get(mag->variable_item_list, VarItemListIndexAllowUART),
  224. mag->state.allow_uart ? "ON" : "OFF");
  225. }
  226. }
  227. #endif
  228. bool mag_scene_settings_on_event(void* context, SceneManagerEvent event) {
  229. Mag* mag = context;
  230. SceneManager* scene_manager = mag->scene_manager;
  231. bool consumed = false;
  232. switch(event.type) {
  233. case SceneManagerEventTypeBack:
  234. // when attempting to exit, validate pin configuration
  235. // if invalid, prompt
  236. consumed = true;
  237. if(!mag_state_gpio_is_valid(&mag->state)) {
  238. mag_scene_settings_dialog_invalid_pins(mag);
  239. } else {
  240. scene_manager_previous_scene(scene_manager);
  241. }
  242. break;
  243. #ifndef FW_ORIGIN_Official
  244. case SceneManagerEventTypeCustom:
  245. scene_manager_set_scene_state(mag->scene_manager, MagSceneSettings, event.event);
  246. consumed = true;
  247. if(event.event == VarItemListIndexAllowUART) {
  248. mag_scene_settings_dialog_allow_uart(mag);
  249. }
  250. break;
  251. #endif
  252. default:
  253. break;
  254. }
  255. return consumed;
  256. }
  257. void mag_scene_settings_on_exit(void* context) {
  258. Mag* mag = context;
  259. variable_item_list_reset(mag->variable_item_list);
  260. mag_state_save(&mag->state);
  261. }